From 60c80d19cca722203ba6149333da8c30303aa072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Wed, 25 Aug 2021 13:14:01 +0200 Subject: [PATCH 1/5] Await the next animation frame between core data API calls in __experimentalBatch() --- packages/core-data/src/actions.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 6c3d392c31210b..3a35e45f24551e 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -643,7 +643,16 @@ export function* __experimentalBatch( requests ) { ); }, }; - const resultPromises = requests.map( ( request ) => request( api ) ); + const resultPromises = []; + const awaitNextFrame = () => __unstableAwaitPromise( new Promise( window.requestAnimationFrame ) ); + for ( const request of requests ) { + resultPromises.push( request( api ) ); + + // Each request( api ) is pretty fast, but when there's a lot of them it may block the browser for a few + // seconds. Let's split this long, blocking task into bite-sized pieces scheduled separately to give the + // browser a space for processing other tasks. + yield awaitNextFrame(); + } const [ , ...results ] = yield __unstableAwaitPromise( Promise.all( [ batch.run(), ...resultPromises ] ) ); From d9b7bb9149b3b461e1391664917ca863f11865f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Wed, 25 Aug 2021 13:14:24 +0200 Subject: [PATCH 2/5] Lint --- packages/core-data/src/actions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 3a35e45f24551e..2c1f88a8475aab 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -644,7 +644,8 @@ export function* __experimentalBatch( requests ) { }, }; const resultPromises = []; - const awaitNextFrame = () => __unstableAwaitPromise( new Promise( window.requestAnimationFrame ) ); + const awaitNextFrame = () => + __unstableAwaitPromise( new Promise( window.requestAnimationFrame ) ); for ( const request of requests ) { resultPromises.push( request( api ) ); From 5fb1765f253acefca5c7556c5b47cd053c458586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Wed, 25 Aug 2021 17:46:51 +0200 Subject: [PATCH 3/5] Fix unit tests --- packages/core-data/src/actions.js | 2 +- packages/core-data/src/test/actions.js | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 2c1f88a8475aab..74478edbecbc96 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -645,7 +645,7 @@ export function* __experimentalBatch( requests ) { }; const resultPromises = []; const awaitNextFrame = () => - __unstableAwaitPromise( new Promise( window.requestAnimationFrame ) ); + __unstableAwaitPromise( new Promise( resolve => window.requestAnimationFrame( () => resolve() ) ) ); for ( const request of requests ) { resultPromises.push( request( api ) ); diff --git a/packages/core-data/src/test/actions.js b/packages/core-data/src/test/actions.js index 6dfec991e2a03d..1969b19e95ac3f 100644 --- a/packages/core-data/src/test/actions.js +++ b/packages/core-data/src/test/actions.js @@ -340,8 +340,13 @@ describe( '__experimentalBatch', () => { ), }; const dispatch = () => actions; + // Run generator up to the last `yield awaitNextFrame( )`. + generator.next( dispatch ) + generator.next(); + generator.next(); + const { value: awaitPromiseControl } = generator.next(); + // Run generator up to `yield __unstableAwaitPromise( ... )`. - const { value: awaitPromiseControl } = generator.next( dispatch ); expect( actions.saveEntityRecord ).toHaveBeenCalledWith( 'root', 'widget', From 24eadcf84e6104485e7b8c03cf524ef9bd952d0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Wed, 25 Aug 2021 17:47:05 +0200 Subject: [PATCH 4/5] Lint --- packages/core-data/src/actions.js | 6 +++++- packages/core-data/src/test/actions.js | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 74478edbecbc96..57f7239e053e2a 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -645,7 +645,11 @@ export function* __experimentalBatch( requests ) { }; const resultPromises = []; const awaitNextFrame = () => - __unstableAwaitPromise( new Promise( resolve => window.requestAnimationFrame( () => resolve() ) ) ); + __unstableAwaitPromise( + new Promise( ( resolve ) => + window.requestAnimationFrame( () => resolve() ) + ) + ); for ( const request of requests ) { resultPromises.push( request( api ) ); diff --git a/packages/core-data/src/test/actions.js b/packages/core-data/src/test/actions.js index 1969b19e95ac3f..3cbd57238b491f 100644 --- a/packages/core-data/src/test/actions.js +++ b/packages/core-data/src/test/actions.js @@ -341,7 +341,7 @@ describe( '__experimentalBatch', () => { }; const dispatch = () => actions; // Run generator up to the last `yield awaitNextFrame( )`. - generator.next( dispatch ) + generator.next( dispatch ); generator.next(); generator.next(); const { value: awaitPromiseControl } = generator.next(); From 9e7e872b619cb72f75df209c2b484837167fc50d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Wed, 25 Aug 2021 18:00:15 +0200 Subject: [PATCH 5/5] Add a comment stating that this, ideally, is only a temporary solution until we can get into a better place with async thunks --- packages/core-data/src/actions.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 57f7239e053e2a..4a19ee1d9c472f 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -656,6 +656,9 @@ export function* __experimentalBatch( requests ) { // Each request( api ) is pretty fast, but when there's a lot of them it may block the browser for a few // seconds. Let's split this long, blocking task into bite-sized pieces scheduled separately to give the // browser a space for processing other tasks. + // + // Ideally this will be just a temporary fix and the blocking would not be an issue in the first place. + // Replacing redux-rungen usage with async thunks may help with that, see https://github.com/WordPress/gutenberg/pull/27276 yield awaitNextFrame(); } const [ , ...results ] = yield __unstableAwaitPromise(