@@ -14,10 +14,11 @@ import {
14
14
import devtools from "./devtools/Devtools" ;
15
15
import { hideStateInstanceInNewObject } from "./hide-object" ;
16
16
import {
17
+ AbortedState ,
17
18
AbortFn ,
18
19
AsyncStateSubscribeProps ,
19
20
CachedState ,
20
- CreateSourceObject ,
21
+ CreateSourceObject , ErrorState ,
21
22
ForkConfig ,
22
23
HydrationData ,
23
24
InitialState ,
@@ -30,7 +31,7 @@ import {
30
31
InstanceEventHandlerType ,
31
32
InstanceEvents ,
32
33
InstanceEventType ,
33
- LibraryPoolsContext ,
34
+ LibraryPoolsContext , PendingState ,
34
35
PendingTimeout ,
35
36
PendingUpdate ,
36
37
PoolInterface ,
@@ -80,7 +81,7 @@ export class AsyncState<T, E, R> implements StateInterface<T, E, R> {
80
81
queue ?: UpdateQueue < T , E , R > ;
81
82
flushing ?: boolean ;
82
83
83
- originalProducer : Producer < T , E , R > | undefined ;
84
+ _producer : Producer < T , E , R > | undefined ;
84
85
85
86
//
86
87
payload ?: Record < string , any > ;
@@ -113,40 +114,49 @@ export class AsyncState<T, E, R> implements StateInterface<T, E, R> {
113
114
poolName ?: string ,
114
115
) {
115
116
116
- let executionContext = requestContext ( config ? .context ) ;
117
- let { poolInUse, getOrCreatePool} = executionContext ;
117
+ let ctx = config && config . context ;
118
+ let { poolInUse : poolToUse , getOrCreatePool} = requestContext ( ctx ) ;
118
119
119
- let poolToUse : PoolInterface = poolInUse ;
120
120
if ( poolName ) {
121
121
poolToUse = getOrCreatePool ( poolName ) ;
122
122
}
123
123
124
- let maybeInstance = poolToUse . instances . get ( key ) ;
124
+ let maybeInstance = poolToUse . instances
125
+ . get ( key ) as AsyncState < T , E , R > | undefined ;
126
+
125
127
if ( maybeInstance ) {
126
128
if ( __DEV__ ) {
127
129
warnAboutAlreadyExistingSourceWithSameKey ( key ) ;
128
130
}
131
+ maybeInstance . replaceProducer ( producer || undefined ) ;
132
+ maybeInstance . patchConfig ( config ) ;
133
+ return maybeInstance ;
134
+ }
129
135
130
- let instance = maybeInstance as AsyncState < T , E , R > ;
131
- instance . replaceProducer ( producer || undefined ) ;
132
- instance . patchConfig ( config ) ;
133
- return instance ;
136
+ this . bindMethods ( ) ;
137
+ if ( __DEV__ ) {
138
+ this . journal = [ ] ;
134
139
}
140
+ poolToUse . set ( key , this ) ;
135
141
136
142
this . key = key ;
137
143
this . pool = poolToUse ;
138
144
this . uniqueId = nextUniqueId ( ) ;
145
+ this . _source = makeSource ( this ) ;
139
146
this . config = shallowClone ( config ) ;
140
- this . originalProducer = producer ?? undefined ;
141
-
142
- if ( __DEV__ ) {
143
- this . journal = [ ] ;
144
- }
147
+ this . _producer = producer ?? undefined ;
145
148
146
149
loadCache ( this ) ;
150
+ let instance = this ;
151
+ this . producer = producerWrapper . bind ( null , {
152
+ instance : this ,
153
+ setState : this . setState ,
154
+ getProducer : ( ) => instance . _producer ,
155
+ replaceState : this . replaceState . bind ( this ) ,
156
+ setSuspender : ( suspender : Promise < T > ) => instance . suspender = suspender ,
157
+ } ) ;
147
158
148
159
let maybeHydratedState = attemptHydratedState < T , E , R > ( this . pool . name , this . key ) ;
149
-
150
160
if ( maybeHydratedState ) {
151
161
this . state = maybeHydratedState . state ;
152
162
this . payload = maybeHydratedState . payload ;
@@ -168,26 +178,9 @@ export class AsyncState<T, E, R> implements StateInterface<T, E, R> {
168
178
this . lastSuccess = this . state ;
169
179
}
170
180
171
-
172
- this . bindMethods ( ) ;
173
-
174
- let instance = this ;
175
- this . producer = producerWrapper . bind ( null , {
176
- setState : instance . setState ,
177
- getState : instance . getState ,
178
- instance : instance ,
179
- setSuspender : ( suspender : Promise < T > ) => instance . suspender = suspender ,
180
- replaceState : instance . replaceState . bind ( instance ) ,
181
- getProducer : ( ) => instance . originalProducer ,
182
- } ) ;
183
-
184
- this . _source = makeSource ( this ) ;
185
-
186
181
if ( __DEV__ ) {
187
182
devtools . emitCreation ( this ) ;
188
183
}
189
-
190
- poolToUse . set ( key , this ) ;
191
184
}
192
185
193
186
private bindMethods ( ) {
@@ -312,7 +305,8 @@ export class AsyncState<T, E, R> implements StateInterface<T, E, R> {
312
305
313
306
replaceState (
314
307
newState : State < T , E , R > ,
315
- notify : boolean = true
308
+ notify : boolean = true ,
309
+ callbacks ?: ProducerCallbacks < T , E , R >
316
310
) : void {
317
311
let { config} = this ;
318
312
let isPending = newState . status === pending ;
@@ -322,7 +316,7 @@ export class AsyncState<T, E, R> implements StateInterface<T, E, R> {
322
316
}
323
317
324
318
if ( this . queue ) {
325
- enqueueUpdate ( this , newState ) ;
319
+ enqueueUpdate ( this , newState , callbacks ) ;
326
320
return ;
327
321
}
328
322
@@ -331,7 +325,7 @@ export class AsyncState<T, E, R> implements StateInterface<T, E, R> {
331
325
this . state . status === pending &&
332
326
! this . flushing
333
327
) {
334
- enqueueUpdate ( this , newState ) ;
328
+ enqueueUpdate ( this , newState , callbacks ) ;
335
329
return ;
336
330
}
337
331
@@ -356,6 +350,7 @@ export class AsyncState<T, E, R> implements StateInterface<T, E, R> {
356
350
if ( __DEV__ ) devtools . startUpdate ( this ) ;
357
351
this . state = newState ;
358
352
this . version += 1 ;
353
+ invokeChangeCallbacks ( newState , callbacks ) ;
359
354
invokeInstanceEvents ( this , "change" ) ;
360
355
if ( __DEV__ ) devtools . emitUpdate ( this ) ;
361
356
@@ -420,15 +415,12 @@ export class AsyncState<T, E, R> implements StateInterface<T, E, R> {
420
415
return cleanup ;
421
416
}
422
417
423
- setState (
424
- newValue : T | StateFunctionUpdater < T , E , R > ,
425
- status = success ,
426
- ) : void {
418
+ setState ( newValue : T | StateFunctionUpdater < T , E , R > , status : Status = success , callbacks ?: ProducerCallbacks < T , E , R > ) : void {
427
419
if ( ! StateBuilder [ status ] ) {
428
420
throw new Error ( `Unknown status ('${ status } ')` ) ;
429
421
}
430
422
if ( this . queue ) {
431
- enqueueSetState ( this , newValue , status ) ;
423
+ enqueueSetState ( this , newValue , status , callbacks ) ;
432
424
return ;
433
425
}
434
426
this . willUpdate = true ;
@@ -450,7 +442,7 @@ export class AsyncState<T, E, R> implements StateInterface<T, E, R> {
450
442
if ( __DEV__ ) devtools . emitReplaceState ( this , savedProps ) ;
451
443
// @ts -ignore
452
444
let newState = StateBuilder [ status ] ( effectiveValue , savedProps ) as State < T , E , R > ;
453
- this . replaceState ( newState ) ;
445
+ this . replaceState ( newState , true , callbacks ) ;
454
446
this . willUpdate = false ;
455
447
}
456
448
@@ -464,7 +456,7 @@ export class AsyncState<T, E, R> implements StateInterface<T, E, R> {
464
456
}
465
457
466
458
replaceProducer ( newProducer : Producer < T , E , R > | undefined ) {
467
- this . originalProducer = newProducer ;
459
+ this . _producer = newProducer ;
468
460
}
469
461
470
462
invalidateCache ( cacheKey ?: string ) {
@@ -601,7 +593,7 @@ export class AsyncState<T, E, R> implements StateInterface<T, E, R> {
601
593
if ( cachedState ) {
602
594
if ( didNotExpire ( cachedState ) ) {
603
595
if ( cachedState . state !== this . state ) {
604
- this . replaceState ( cachedState . state ) ;
596
+ this . replaceState ( cachedState . state , true , runProps ) ;
605
597
}
606
598
if ( __DEV__ ) devtools . emitRunConsumedFromCache ( this , payload , execArgs ) ;
607
599
return ;
@@ -692,7 +684,7 @@ export class AsyncState<T, E, R> implements StateInterface<T, E, R> {
692
684
key = `${ this . key } -fork-${ this . forksIndex + 1 } ` ;
693
685
}
694
686
695
- const clone = new AsyncState ( key , this . originalProducer , this . config , this . pool . simpleName ) ;
687
+ const clone = new AsyncState ( key , this . _producer , this . config , this . pool . simpleName ) ;
696
688
697
689
// if something fail, no need to increment
698
690
this . forksIndex += 1 ;
@@ -730,6 +722,25 @@ export class AsyncState<T, E, R> implements StateInterface<T, E, R> {
730
722
731
723
//region AsyncState methods helpers
732
724
725
+ function invokeChangeCallbacks < T , E , R > (
726
+ state : State < T , E , R > ,
727
+ callbacks : ProducerCallbacks < T , E , R > | undefined
728
+ ) {
729
+ if ( ! callbacks ) {
730
+ return ;
731
+ }
732
+ let { onError, onAborted, onSuccess} = callbacks ;
733
+ if ( onSuccess && state . status === success ) {
734
+ onSuccess ( state ) ;
735
+ }
736
+ if ( onAborted && state . status === aborted ) {
737
+ onAborted ( state ) ;
738
+ }
739
+ if ( onError && state . status === error ) {
740
+ onError ( state ) ;
741
+ }
742
+ }
743
+
733
744
export function shallowClone (
734
745
source1 ,
735
746
source2 ?
@@ -738,7 +749,9 @@ export function shallowClone(
738
749
}
739
750
740
751
export function attemptHydratedState < T , E , R > (
741
- poolName : string , key : string ) : HydrationData < T , E , R > | null {
752
+ poolName : string ,
753
+ key : string
754
+ ) : HydrationData < T , E , R > | null {
742
755
// do not attempt hydration outside server
743
756
if ( isServer ) {
744
757
return null ;
@@ -871,7 +884,7 @@ function constructPropsObject<T, E, R>(
871
884
return ;
872
885
}
873
886
instance . isEmitting = true ;
874
- instance . setState ( updater , status ) ;
887
+ instance . setState ( updater , status , callbacks ) ;
875
888
instance . isEmitting = false ;
876
889
}
877
890
@@ -891,8 +904,7 @@ function constructPropsObject<T, E, R>(
891
904
// these state updates are only with aborted status
892
905
if ( ! instance . willUpdate ) {
893
906
let abortedState = StateBuilder . aborted < T , E , R > ( reason , cloneProducerProps ( props ) ) ;
894
- instance . replaceState ( abortedState ) ;
895
- callbacks ?. onAborted ?.( abortedState ) ;
907
+ instance . replaceState ( abortedState , true , callbacks ) ;
896
908
}
897
909
}
898
910
@@ -1307,8 +1319,10 @@ function getQueueTail<T, E, R>(instance: StateInterface<T, E, R>): UpdateQueue<T
1307
1319
export function enqueueUpdate < T , E , R > (
1308
1320
instance : StateInterface < T , E , R > ,
1309
1321
newState : State < T , E , R > ,
1322
+ callbacks ?: ProducerCallbacks < T , E , R >
1310
1323
) {
1311
1324
let update : UpdateQueue < T , E , R > = {
1325
+ callbacks,
1312
1326
data : newState ,
1313
1327
kind : 0 ,
1314
1328
next : null ,
@@ -1330,8 +1344,10 @@ export function enqueueSetState<T, E, R>(
1330
1344
instance : StateInterface < T , E , R > ,
1331
1345
newValue : T | StateFunctionUpdater < T , E , R > ,
1332
1346
status = success ,
1347
+ callbacks ?: ProducerCallbacks < T , E , R > ,
1333
1348
) {
1334
1349
let update : UpdateQueue < T , E , R > = {
1350
+ callbacks,
1335
1351
kind : 1 ,
1336
1352
data : { data : newValue , status} ,
1337
1353
next : null ,
@@ -1384,18 +1400,18 @@ function flushUpdateQueue<T, E, R>(
1384
1400
1385
1401
instance . flushing = true ;
1386
1402
while ( current !== null ) {
1387
- let { data : { status} } = current ;
1403
+ let { data : { status} , callbacks } = current ;
1388
1404
let canBailoutPendingStatus = status === pending && current . next !== null ;
1389
1405
1390
1406
if ( canBailoutPendingStatus ) {
1391
1407
current = current . next ;
1392
1408
} else {
1393
1409
if ( current . kind === 0 ) {
1394
- instance . replaceState ( current . data ) ;
1410
+ instance . replaceState ( current . data , undefined , callbacks ) ;
1395
1411
}
1396
1412
if ( current . kind === 1 ) {
1397
1413
let { data : { data, status} } = current ;
1398
- instance . setState ( data , status ) ;
1414
+ instance . setState ( data , status , callbacks ) ;
1399
1415
}
1400
1416
current = current . next ;
1401
1417
}
0 commit comments