@@ -2,11 +2,13 @@ import {
2
2
Updater ,
3
3
deepIncludes ,
4
4
functionalUpdate ,
5
+ getBatchedUpdates ,
5
6
getQueryArgs ,
6
7
isDocumentVisible ,
7
- isPlainObject ,
8
8
isOnline ,
9
+ isPlainObject ,
9
10
isServer ,
11
+ scheduleMicrotask ,
10
12
} from './utils'
11
13
import { getResolvedQueryConfig } from './config'
12
14
import { Query } from './query'
@@ -66,6 +68,8 @@ type QueryCacheListener = (
66
68
query ?: Query < unknown , unknown >
67
69
) => void
68
70
71
+ type NotifyCallback = ( ) => void
72
+
69
73
// CLASS
70
74
71
75
export class QueryCache {
@@ -75,13 +79,44 @@ export class QueryCache {
75
79
private globalListeners : QueryCacheListener [ ]
76
80
private queries : QueryHashMap
77
81
private queriesArray : Query < any , any > [ ]
82
+ private notifyQueue : NotifyCallback [ ]
83
+ private notifyTransactions : number
78
84
79
85
constructor ( config ?: QueryCacheConfig ) {
80
86
this . config = config || { }
81
87
this . globalListeners = [ ]
82
88
this . queries = { }
83
89
this . queriesArray = [ ]
84
90
this . isFetching = 0
91
+ this . notifyQueue = [ ]
92
+ this . notifyTransactions = 0
93
+ }
94
+
95
+ batchNotifications ( callback : ( ) => void ) : void {
96
+ this . notifyTransactions ++
97
+ callback ( )
98
+ this . notifyTransactions --
99
+ if ( ! this . notifyTransactions && this . notifyQueue . length ) {
100
+ scheduleMicrotask ( ( ) => {
101
+ const batchedUpdates = getBatchedUpdates ( )
102
+ batchedUpdates ( ( ) => {
103
+ this . notifyQueue . forEach ( notify => {
104
+ notify ( )
105
+ } )
106
+ this . notifyQueue = [ ]
107
+ } )
108
+ } )
109
+ }
110
+ }
111
+
112
+ scheduleNotification ( notify : NotifyCallback ) : void {
113
+ if ( this . notifyTransactions ) {
114
+ this . notifyQueue . push ( notify )
115
+ } else {
116
+ scheduleMicrotask ( ( ) => {
117
+ notify ( )
118
+ } )
119
+ }
85
120
}
86
121
87
122
notifyGlobalListeners ( query ?: Query < any , any > ) {
@@ -91,7 +126,9 @@ export class QueryCache {
91
126
)
92
127
93
128
this . globalListeners . forEach ( listener => {
94
- listener ( this , query )
129
+ this . scheduleNotification ( ( ) => {
130
+ listener ( this , query )
131
+ } )
95
132
} )
96
133
}
97
134
@@ -195,17 +232,18 @@ export class QueryCache {
195
232
options || { }
196
233
197
234
try {
198
- await Promise . all (
199
- this . getQueries ( predicate , options ) . map ( query => {
200
- const enabled = query . isEnabled ( )
235
+ const promises : Promise < unknown > [ ] = [ ]
201
236
237
+ this . batchNotifications ( ( ) => {
238
+ this . getQueries ( predicate , options ) . forEach ( query => {
239
+ const enabled = query . isEnabled ( )
202
240
if ( ( enabled && refetchActive ) || ( ! enabled && refetchInactive ) ) {
203
- return query . fetch ( )
241
+ promises . push ( query . fetch ( ) )
204
242
}
205
-
206
- return undefined
207
243
} )
208
- )
244
+ } )
245
+
246
+ await Promise . all ( promises )
209
247
} catch ( err ) {
210
248
if ( throwOnError ) {
211
249
throw err
@@ -363,8 +401,10 @@ export function makeQueryCache(config?: QueryCacheConfig) {
363
401
export function onVisibilityOrOnlineChange ( type : 'focus' | 'online' ) {
364
402
if ( isDocumentVisible ( ) && isOnline ( ) ) {
365
403
queryCaches . forEach ( queryCache => {
366
- queryCache . getQueries ( ) . forEach ( query => {
367
- query . onInteraction ( type )
404
+ queryCache . batchNotifications ( ( ) => {
405
+ queryCache . getQueries ( ) . forEach ( query => {
406
+ query . onInteraction ( type )
407
+ } )
368
408
} )
369
409
} )
370
410
}
0 commit comments