@@ -4,29 +4,34 @@ import {
44 difference ,
55 filter ,
66 flatten ,
7+ forEach ,
78 groupBy ,
89 includes ,
910 intersection ,
1011 isEmpty ,
1112 isNil ,
1213 map ,
14+ mergeLeft ,
15+ mergeWith ,
16+ pluck ,
17+ reduce ,
1318 values
1419} from 'ramda' ;
1520
1621import { IStoreState } from '../store' ;
1722
1823import {
1924 aggregateCallbacks ,
20- removeRequestedCallbacks ,
2125 removePrioritizedCallbacks ,
2226 removeExecutingCallbacks ,
2327 removeWatchedCallbacks ,
24- addRequestedCallbacks ,
2528 addPrioritizedCallbacks ,
2629 addExecutingCallbacks ,
2730 addWatchedCallbacks ,
2831 removeBlockedCallbacks ,
29- addBlockedCallbacks
32+ addBlockedCallbacks ,
33+ addRequestedCallbacks ,
34+ removeRequestedCallbacks
3035} from '../actions/callbacks' ;
3136
3237import { isMultiValued } from '../actions/dependencies' ;
@@ -45,17 +50,23 @@ import {
4550 IBlockedCallback
4651} from '../types/callbacks' ;
4752
53+ import wait from './../utils/wait' ;
54+
4855import { getPendingCallbacks } from '../utils/callbacks' ;
4956import { IStoreObserverDefinition } from '../StoreObserver' ;
5057
5158const observer : IStoreObserverDefinition < IStoreState > = {
52- observer : ( {
59+ observer : async ( {
5360 dispatch,
5461 getState
5562 } ) => {
63+ await wait ( 0 ) ;
64+
5665 const { callbacks, callbacks : { prioritized, blocked, executing, watched, stored } , paths } = getState ( ) ;
5766 let { callbacks : { requested } } = getState ( ) ;
5867
68+ const initialRequested = requested . slice ( 0 ) ;
69+
5970 const pendingCallbacks = getPendingCallbacks ( callbacks ) ;
6071
6172 /*
@@ -78,17 +89,37 @@ const observer: IStoreObserverDefinition<IStoreState> = {
7889 1. Remove duplicated `requested` callbacks - give precedence to newer callbacks over older ones
7990 */
8091
81- /*
82- Extract all but the first callback from each IOS-key group
83- these callbacks are duplicates.
84- */
85- const rDuplicates = flatten ( map (
86- group => group . slice ( 0 , - 1 ) ,
87- values (
88- groupBy < ICallback > (
89- getUniqueIdentifier ,
90- requested
91- )
92+ let rDuplicates : ICallback [ ] = [ ] ;
93+ let rMergedDuplicates : ICallback [ ] = [ ] ;
94+
95+ forEach ( group => {
96+ if ( group . length === 1 ) {
97+ // keep callback if its the only one of its kind
98+ rMergedDuplicates . push ( group [ 0 ] ) ;
99+ } else {
100+ const initial = group . find ( cb => cb . initialCall ) ;
101+ if ( initial ) {
102+ // drop the initial callback if it's not alone
103+ rDuplicates . push ( initial ) ;
104+ }
105+
106+ const groupWithoutInitial = group . filter ( cb => cb !== initial ) ;
107+ if ( groupWithoutInitial . length === 1 ) {
108+ // if there's only one callback beside the initial one, keep that callback
109+ rMergedDuplicates . push ( groupWithoutInitial [ 0 ] ) ;
110+ } else {
111+ // otherwise merge all remaining callbacks together
112+ rDuplicates = concat ( rDuplicates , groupWithoutInitial ) ;
113+ rMergedDuplicates . push ( mergeLeft ( {
114+ changedPropIds : reduce ( mergeWith ( Math . max ) , { } , pluck ( 'changedPropIds' , groupWithoutInitial ) ) ,
115+ executionGroup : filter ( exg => ! ! exg , pluck ( 'executionGroup' , groupWithoutInitial ) ) . slice ( - 1 ) [ 0 ]
116+ } , groupWithoutInitial . slice ( - 1 ) [ 0 ] ) as ICallback ) ;
117+ }
118+ }
119+ } , values (
120+ groupBy < ICallback > (
121+ getUniqueIdentifier ,
122+ requested
92123 )
93124 ) ) ;
94125
@@ -97,7 +128,7 @@ const observer: IStoreObserverDefinition<IStoreState> = {
97128 Clean up the `requested` list - during the dispatch phase,
98129 duplicates will be removed for real
99130 */
100- requested = difference ( requested , rDuplicates ) ;
131+ requested = rMergedDuplicates ;
101132
102133 /*
103134 2. Remove duplicated `prioritized`, `executing` and `watching` callbacks
@@ -312,16 +343,24 @@ const observer: IStoreObserverDefinition<IStoreState> = {
312343 dropped
313344 ) ;
314345
346+ requested = difference (
347+ requested ,
348+ readyCallbacks
349+ ) ;
350+
351+ const added = difference ( requested , initialRequested ) ;
352+ const removed = difference ( initialRequested , requested ) ;
353+
315354 dispatch ( aggregateCallbacks ( [
355+ // Clean up requested callbacks
356+ added . length ? addRequestedCallbacks ( added ) : null ,
357+ removed . length ? removeRequestedCallbacks ( removed ) : null ,
316358 // Clean up duplicated callbacks
317- rDuplicates . length ? removeRequestedCallbacks ( rDuplicates ) : null ,
318359 pDuplicates . length ? removePrioritizedCallbacks ( pDuplicates ) : null ,
319360 bDuplicates . length ? removeBlockedCallbacks ( bDuplicates ) : null ,
320361 eDuplicates . length ? removeExecutingCallbacks ( eDuplicates ) : null ,
321362 wDuplicates . length ? removeWatchedCallbacks ( wDuplicates ) : null ,
322363 // Prune callbacks
323- rRemoved . length ? removeRequestedCallbacks ( rRemoved ) : null ,
324- rAdded . length ? addRequestedCallbacks ( rAdded ) : null ,
325364 pRemoved . length ? removePrioritizedCallbacks ( pRemoved ) : null ,
326365 pAdded . length ? addPrioritizedCallbacks ( pAdded ) : null ,
327366 bRemoved . length ? removeBlockedCallbacks ( bRemoved ) : null ,
@@ -330,15 +369,7 @@ const observer: IStoreObserverDefinition<IStoreState> = {
330369 eAdded . length ? addExecutingCallbacks ( eAdded ) : null ,
331370 wRemoved . length ? removeWatchedCallbacks ( wRemoved ) : null ,
332371 wAdded . length ? addWatchedCallbacks ( wAdded ) : null ,
333- // Prune circular callbacks
334- rCirculars . length ? removeRequestedCallbacks ( rCirculars ) : null ,
335- // Prune circular assumptions
336- oldBlocked . length ? removeRequestedCallbacks ( oldBlocked ) : null ,
337- newBlocked . length ? addRequestedCallbacks ( newBlocked ) : null ,
338- // Drop non-triggered initial callbacks
339- dropped . length ? removeRequestedCallbacks ( dropped ) : null ,
340372 // Promote callbacks
341- readyCallbacks . length ? removeRequestedCallbacks ( readyCallbacks ) : null ,
342373 readyCallbacks . length ? addPrioritizedCallbacks ( readyCallbacks ) : null
343374 ] ) ) ;
344375 } ,
0 commit comments