diff --git a/data/index.js b/data/index.js index abd3f94299bbc1..fd2435e78e8b33 100644 --- a/data/index.js +++ b/data/index.js @@ -28,13 +28,7 @@ let listeners = []; * Global listener called for each store's update. */ export function globalListener() { - // Use for loop instead of Array#forEach, as it's possible a listener's - // behavior causes one further in the stack to be unsubscribed. The - // latter's callback should not be called, which requires monitoring - // changes to the array as they occur in iteration. - for ( let i = 0; i < listeners.length; i++ ) { - listeners[ i ](); - } + listeners.forEach( ( listener ) => listener() ); } /** diff --git a/data/test/index.js b/data/test/index.js index 488e47e579dd00..b89e8f87aa324a 100644 --- a/data/test/index.js +++ b/data/test/index.js @@ -248,7 +248,21 @@ describe( 'subscribe', () => { expect( incrementedValue ).toBe( 3 ); } ); - it( 'avoids calling a later listener if unsubscribed during earlier callback', () => { + it( 'snapshots listeners on change, avoiding a later listener if subscribed during earlier callback', () => { + const store = registerReducer( 'myAwesomeReducer', ( state = 0 ) => state + 1 ); + const secondListener = jest.fn(); + const firstListener = jest.fn( () => { + subscribeWithUnsubscribe( secondListener ); + } ); + + subscribeWithUnsubscribe( firstListener ); + + store.dispatch( { type: 'dummy' } ); + + expect( secondListener ).not.toHaveBeenCalled(); + } ); + + it( 'snapshots listeners on change, calling a later listener even if unsubscribed during earlier callback', () => { const store = registerReducer( 'myAwesomeReducer', ( state = 0 ) => state + 1 ); const firstListener = jest.fn( () => { secondUnsubscribe(); @@ -260,7 +274,7 @@ describe( 'subscribe', () => { store.dispatch( { type: 'dummy' } ); - expect( secondListener ).not.toHaveBeenCalled(); + expect( secondListener ).toHaveBeenCalled(); } ); } );