@@ -4,29 +4,34 @@ import {
4
4
difference ,
5
5
filter ,
6
6
flatten ,
7
+ forEach ,
7
8
groupBy ,
8
9
includes ,
9
10
intersection ,
10
11
isEmpty ,
11
12
isNil ,
12
13
map ,
14
+ mergeLeft ,
15
+ mergeWith ,
16
+ pluck ,
17
+ reduce ,
13
18
values
14
19
} from 'ramda' ;
15
20
16
21
import { IStoreState } from '../store' ;
17
22
18
23
import {
19
24
aggregateCallbacks ,
20
- removeRequestedCallbacks ,
21
25
removePrioritizedCallbacks ,
22
26
removeExecutingCallbacks ,
23
27
removeWatchedCallbacks ,
24
- addRequestedCallbacks ,
25
28
addPrioritizedCallbacks ,
26
29
addExecutingCallbacks ,
27
30
addWatchedCallbacks ,
28
31
removeBlockedCallbacks ,
29
- addBlockedCallbacks
32
+ addBlockedCallbacks ,
33
+ addRequestedCallbacks ,
34
+ removeRequestedCallbacks
30
35
} from '../actions/callbacks' ;
31
36
32
37
import { isMultiValued } from '../actions/dependencies' ;
@@ -45,17 +50,23 @@ import {
45
50
IBlockedCallback
46
51
} from '../types/callbacks' ;
47
52
53
+ import wait from './../utils/wait' ;
54
+
48
55
import { getPendingCallbacks } from '../utils/callbacks' ;
49
56
import { IStoreObserverDefinition } from '../StoreObserver' ;
50
57
51
58
const observer : IStoreObserverDefinition < IStoreState > = {
52
- observer : ( {
59
+ observer : async ( {
53
60
dispatch,
54
61
getState
55
62
} ) => {
63
+ await wait ( 0 ) ;
64
+
56
65
const { callbacks, callbacks : { prioritized, blocked, executing, watched, stored } , paths } = getState ( ) ;
57
66
let { callbacks : { requested } } = getState ( ) ;
58
67
68
+ const initialRequested = requested . slice ( 0 ) ;
69
+
59
70
const pendingCallbacks = getPendingCallbacks ( callbacks ) ;
60
71
61
72
/*
@@ -78,17 +89,37 @@ const observer: IStoreObserverDefinition<IStoreState> = {
78
89
1. Remove duplicated `requested` callbacks - give precedence to newer callbacks over older ones
79
90
*/
80
91
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
92
123
)
93
124
) ) ;
94
125
@@ -97,7 +128,7 @@ const observer: IStoreObserverDefinition<IStoreState> = {
97
128
Clean up the `requested` list - during the dispatch phase,
98
129
duplicates will be removed for real
99
130
*/
100
- requested = difference ( requested , rDuplicates ) ;
131
+ requested = rMergedDuplicates ;
101
132
102
133
/*
103
134
2. Remove duplicated `prioritized`, `executing` and `watching` callbacks
@@ -312,16 +343,24 @@ const observer: IStoreObserverDefinition<IStoreState> = {
312
343
dropped
313
344
) ;
314
345
346
+ requested = difference (
347
+ requested ,
348
+ readyCallbacks
349
+ ) ;
350
+
351
+ const added = difference ( requested , initialRequested ) ;
352
+ const removed = difference ( initialRequested , requested ) ;
353
+
315
354
dispatch ( aggregateCallbacks ( [
355
+ // Clean up requested callbacks
356
+ added . length ? addRequestedCallbacks ( added ) : null ,
357
+ removed . length ? removeRequestedCallbacks ( removed ) : null ,
316
358
// Clean up duplicated callbacks
317
- rDuplicates . length ? removeRequestedCallbacks ( rDuplicates ) : null ,
318
359
pDuplicates . length ? removePrioritizedCallbacks ( pDuplicates ) : null ,
319
360
bDuplicates . length ? removeBlockedCallbacks ( bDuplicates ) : null ,
320
361
eDuplicates . length ? removeExecutingCallbacks ( eDuplicates ) : null ,
321
362
wDuplicates . length ? removeWatchedCallbacks ( wDuplicates ) : null ,
322
363
// Prune callbacks
323
- rRemoved . length ? removeRequestedCallbacks ( rRemoved ) : null ,
324
- rAdded . length ? addRequestedCallbacks ( rAdded ) : null ,
325
364
pRemoved . length ? removePrioritizedCallbacks ( pRemoved ) : null ,
326
365
pAdded . length ? addPrioritizedCallbacks ( pAdded ) : null ,
327
366
bRemoved . length ? removeBlockedCallbacks ( bRemoved ) : null ,
@@ -330,15 +369,7 @@ const observer: IStoreObserverDefinition<IStoreState> = {
330
369
eAdded . length ? addExecutingCallbacks ( eAdded ) : null ,
331
370
wRemoved . length ? removeWatchedCallbacks ( wRemoved ) : null ,
332
371
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 ,
340
372
// Promote callbacks
341
- readyCallbacks . length ? removeRequestedCallbacks ( readyCallbacks ) : null ,
342
373
readyCallbacks . length ? addPrioritizedCallbacks ( readyCallbacks ) : null
343
374
] ) ) ;
344
375
} ,
0 commit comments