@@ -9,25 +9,25 @@ import type {
9
9
import { createAction , nanoid } from '@reduxjs/toolkit'
10
10
11
11
import type {
12
- ActionListenerMiddleware ,
12
+ ListenerMiddleware ,
13
+ ListenerMiddlewareInstance ,
13
14
AddListenerOverloads ,
14
- AnyActionListenerPredicate ,
15
+ AnyListenerPredicate ,
15
16
CreateListenerMiddlewareOptions ,
16
17
TypedActionCreator ,
18
+ TypedStartListening ,
17
19
TypedAddListener ,
18
- TypedAddListenerAction ,
19
20
TypedCreateListenerEntry ,
20
21
FallbackAddListenerOptions ,
21
22
ListenerEntry ,
22
23
ListenerErrorHandler ,
23
24
Unsubscribe ,
24
- WithMiddlewareType ,
25
25
TakePattern ,
26
26
ListenerErrorInfo ,
27
27
ForkedTaskExecutor ,
28
28
ForkedTask ,
29
- TypedRemoveListenerAction ,
30
29
TypedRemoveListener ,
30
+ TypedStopListening ,
31
31
} from './types'
32
32
import { assertFunction , catchRejection } from './utils'
33
33
import { TaskAbortError } from './exceptions'
@@ -40,16 +40,15 @@ import {
40
40
} from './task'
41
41
export { TaskAbortError } from './exceptions'
42
42
export type {
43
- ActionListener ,
44
- ActionListenerMiddleware ,
45
- ActionListenerMiddlewareAPI ,
46
- ActionListenerOptions ,
43
+ ListenerEffect ,
44
+ ListenerMiddleware ,
45
+ ListenerEffectAPI ,
47
46
CreateListenerMiddlewareOptions ,
48
47
ListenerErrorHandler ,
48
+ TypedStartListening ,
49
49
TypedAddListener ,
50
- TypedAddListenerAction ,
50
+ TypedStopListening ,
51
51
TypedRemoveListener ,
52
- TypedRemoveListenerAction ,
53
52
Unsubscribe ,
54
53
ForkedTaskExecutor ,
55
54
ForkedTask ,
@@ -69,7 +68,7 @@ const { assign } = Object
69
68
*/
70
69
const INTERNAL_NIL_TOKEN = { } as const
71
70
72
- const alm = 'actionListenerMiddleware ' as const
71
+ const alm = 'listenerMiddleware ' as const
73
72
74
73
const createFork = ( parentAbortSignal : AbortSignal ) => {
75
74
return < T > ( taskExecutor : ForkedTaskExecutor < T > ) : ForkedTask < T > => {
@@ -100,17 +99,17 @@ const createFork = (parentAbortSignal: AbortSignal) => {
100
99
}
101
100
102
101
const createTakePattern = < S > (
103
- addListener : AddListenerOverloads < Unsubscribe , S , Dispatch < AnyAction > > ,
102
+ startListening : AddListenerOverloads < Unsubscribe , S , Dispatch < AnyAction > > ,
104
103
signal : AbortSignal
105
104
) : TakePattern < S > => {
106
105
/**
107
- * A function that takes an ActionListenerPredicate and an optional timeout,
106
+ * A function that takes a ListenerPredicate and an optional timeout,
108
107
* and resolves when either the predicate returns `true` based on an action
109
108
* state combination or when the timeout expires.
110
109
* If the parent listener is canceled while waiting, this will throw a
111
110
* TaskAbortError.
112
111
*/
113
- const take = async < P extends AnyActionListenerPredicate < S > > (
112
+ const take = async < P extends AnyListenerPredicate < S > > (
114
113
predicate : P ,
115
114
timeout : number | undefined
116
115
) => {
@@ -121,9 +120,9 @@ const createTakePattern = <S>(
121
120
122
121
const tuplePromise = new Promise < [ AnyAction , S , S ] > ( ( resolve ) => {
123
122
// Inside the Promise, we synchronously add the listener.
124
- unsubscribe = addListener ( {
123
+ unsubscribe = startListening ( {
125
124
predicate : predicate as any ,
126
- listener : ( action , listenerApi ) : void => {
125
+ effect : ( action , listenerApi ) : void => {
127
126
// One-shot listener that cleans up as soon as the predicate passes
128
127
listenerApi . unsubscribe ( )
129
128
// Resolve the promise with the same arguments the predicate saw
@@ -158,14 +157,12 @@ const createTakePattern = <S>(
158
157
}
159
158
}
160
159
161
- return ( (
162
- predicate : AnyActionListenerPredicate < S > ,
163
- timeout : number | undefined
164
- ) => catchRejection ( take ( predicate , timeout ) ) ) as TakePattern < S >
160
+ return ( ( predicate : AnyListenerPredicate < S > , timeout : number | undefined ) =>
161
+ catchRejection ( take ( predicate , timeout ) ) ) as TakePattern < S >
165
162
}
166
163
167
164
const getListenerEntryPropsFrom = ( options : FallbackAddListenerOptions ) => {
168
- let { type, actionCreator, matcher, predicate, listener } = options
165
+ let { type, actionCreator, matcher, predicate, effect } = options
169
166
170
167
if ( type ) {
171
168
predicate = createAction ( type ) . match
@@ -182,21 +179,21 @@ const getListenerEntryPropsFrom = (options: FallbackAddListenerOptions) => {
182
179
)
183
180
}
184
181
185
- assertFunction ( listener , 'options.listener' )
182
+ assertFunction ( effect , 'options.listener' )
186
183
187
- return { predicate, type, listener }
184
+ return { predicate, type, effect }
188
185
}
189
186
190
187
/** Accepts the possible options for creating a listener, and returns a formatted listener entry */
191
188
export const createListenerEntry : TypedCreateListenerEntry < unknown > = (
192
189
options : FallbackAddListenerOptions
193
190
) => {
194
- const { type, predicate, listener } = getListenerEntryPropsFrom ( options )
191
+ const { type, predicate, effect } = getListenerEntryPropsFrom ( options )
195
192
196
193
const id = nanoid ( )
197
194
const entry : ListenerEntry < unknown > = {
198
195
id,
199
- listener ,
196
+ effect ,
200
197
type,
201
198
predicate,
202
199
pending : new Set < AbortController > ( ) ,
@@ -248,21 +245,21 @@ const safelyNotifyError = (
248
245
/**
249
246
* @alpha
250
247
*/
251
- export const addListenerAction = createAction (
248
+ export const addListener = createAction (
252
249
`${ alm } /add`
253
- ) as TypedAddListenerAction < unknown >
250
+ ) as TypedAddListener < unknown >
254
251
255
252
/**
256
253
* @alpha
257
254
*/
258
- export const clearListenerMiddlewareAction = createAction ( `${ alm } /clear ` )
255
+ export const removeAllListeners = createAction ( `${ alm } /removeAll ` )
259
256
260
257
/**
261
258
* @alpha
262
259
*/
263
- export const removeListenerAction = createAction (
260
+ export const removeListener = createAction (
264
261
`${ alm } /remove`
265
- ) as TypedRemoveListenerAction < unknown >
262
+ ) as TypedRemoveListener < unknown >
266
263
267
264
const defaultErrorHandler : ListenerErrorHandler = ( ...args : unknown [ ] ) => {
268
265
console . error ( `${ alm } /error` , ...args )
@@ -300,9 +297,9 @@ export function createListenerMiddleware<
300
297
return undefined
301
298
}
302
299
303
- const addListener = ( options : FallbackAddListenerOptions ) => {
300
+ const startListening = ( options : FallbackAddListenerOptions ) => {
304
301
let entry = findListenerEntry (
305
- ( existingEntry ) => existingEntry . listener === options . listener
302
+ ( existingEntry ) => existingEntry . effect === options . effect
306
303
)
307
304
308
305
if ( ! entry ) {
@@ -312,16 +309,16 @@ export function createListenerMiddleware<
312
309
return insertEntry ( entry )
313
310
}
314
311
315
- const removeListener = ( options : FallbackAddListenerOptions ) : boolean => {
316
- const { type, listener , predicate } = getListenerEntryPropsFrom ( options )
312
+ const stopListening = ( options : FallbackAddListenerOptions ) : boolean => {
313
+ const { type, effect , predicate } = getListenerEntryPropsFrom ( options )
317
314
318
315
const entry = findListenerEntry ( ( entry ) => {
319
316
const matchPredicateOrType =
320
317
typeof type === 'string'
321
318
? entry . type === type
322
319
: entry . predicate === predicate
323
320
324
- return matchPredicateOrType && entry . listener === listener
321
+ return matchPredicateOrType && entry . effect === effect
325
322
} )
326
323
327
324
entry ?. unsubscribe ( )
@@ -336,18 +333,21 @@ export function createListenerMiddleware<
336
333
getOriginalState : ( ) => S
337
334
) => {
338
335
const internalTaskController = new AbortController ( )
339
- const take = createTakePattern ( addListener , internalTaskController . signal )
336
+ const take = createTakePattern (
337
+ startListening ,
338
+ internalTaskController . signal
339
+ )
340
340
341
341
try {
342
342
entry . pending . add ( internalTaskController )
343
343
await Promise . resolve (
344
- entry . listener (
344
+ entry . effect (
345
345
action ,
346
346
// Use assign() rather than ... to avoid extra helper functions added to bundle
347
347
assign ( { } , api , {
348
348
getOriginalState,
349
349
condition : (
350
- predicate : AnyActionListenerPredicate < any > ,
350
+ predicate : AnyListenerPredicate < any > ,
351
351
timeout ?: number
352
352
) => take ( predicate , timeout ) . then ( Boolean ) ,
353
353
take,
@@ -374,7 +374,7 @@ export function createListenerMiddleware<
374
374
} catch ( listenerError ) {
375
375
if ( ! ( listenerError instanceof TaskAbortError ) ) {
376
376
safelyNotifyError ( onError , listenerError , {
377
- raisedBy : 'listener ' ,
377
+ raisedBy : 'effect ' ,
378
378
} )
379
379
}
380
380
} finally {
@@ -385,84 +385,76 @@ export function createListenerMiddleware<
385
385
386
386
const clearListenerMiddleware = createClearListenerMiddleware ( listenerMap )
387
387
388
- const middleware : Middleware <
389
- {
390
- ( action : Action < `${typeof alm } /add`> ) : Unsubscribe
391
- } ,
392
- S ,
393
- D
394
- > = ( api ) => ( next ) => ( action ) => {
395
- if ( addListenerAction . match ( action ) ) {
396
- return addListener ( action . payload )
397
- }
388
+ const middleware : ListenerMiddleware < S , D , ExtraArgument > =
389
+ ( api ) => ( next ) => ( action ) => {
390
+ if ( addListener . match ( action ) ) {
391
+ return startListening ( action . payload )
392
+ }
398
393
399
- if ( clearListenerMiddlewareAction . match ( action ) ) {
400
- clearListenerMiddleware ( )
401
- return
402
- }
394
+ if ( removeAllListeners . match ( action ) ) {
395
+ clearListenerMiddleware ( )
396
+ return
397
+ }
403
398
404
- if ( removeListenerAction . match ( action ) ) {
405
- return removeListener ( action . payload )
406
- }
399
+ if ( removeListener . match ( action ) ) {
400
+ return stopListening ( action . payload )
401
+ }
407
402
408
- // Need to get this state _before_ the reducer processes the action
409
- let originalState : S | typeof INTERNAL_NIL_TOKEN = api . getState ( )
403
+ // Need to get this state _before_ the reducer processes the action
404
+ let originalState : S | typeof INTERNAL_NIL_TOKEN = api . getState ( )
410
405
411
- // `getOriginalState` can only be called synchronously.
412
- // @see https://github.com/reduxjs/redux-toolkit/discussions/1648#discussioncomment-1932820
413
- const getOriginalState = ( ) : S => {
414
- if ( originalState === INTERNAL_NIL_TOKEN ) {
415
- throw new Error (
416
- `${ alm } : getOriginalState can only be called synchronously`
417
- )
406
+ // `getOriginalState` can only be called synchronously.
407
+ // @see https://github.com/reduxjs/redux-toolkit/discussions/1648#discussioncomment-1932820
408
+ const getOriginalState = ( ) : S => {
409
+ if ( originalState === INTERNAL_NIL_TOKEN ) {
410
+ throw new Error (
411
+ `${ alm } : getOriginalState can only be called synchronously`
412
+ )
413
+ }
414
+
415
+ return originalState as S
418
416
}
419
417
420
- return originalState as S
421
- }
418
+ let result : unknown
422
419
423
- let result : unknown
420
+ try {
421
+ // Actually forward the action to the reducer before we handle listeners
422
+ result = next ( action )
424
423
425
- try {
426
- // Actually forward the action to the reducer before we handle listeners
427
- result = next ( action )
428
-
429
- if ( listenerMap . size > 0 ) {
430
- let currentState = api . getState ( )
431
- for ( let entry of listenerMap . values ( ) ) {
432
- let runListener = false
433
-
434
- try {
435
- runListener = entry . predicate ( action , currentState , originalState )
436
- } catch ( predicateError ) {
437
- runListener = false
438
-
439
- safelyNotifyError ( onError , predicateError , {
440
- raisedBy : 'predicate' ,
441
- } )
442
- }
424
+ if ( listenerMap . size > 0 ) {
425
+ let currentState = api . getState ( )
426
+ for ( let entry of listenerMap . values ( ) ) {
427
+ let runListener = false
443
428
444
- if ( ! runListener ) {
445
- continue
446
- }
429
+ try {
430
+ runListener = entry . predicate ( action , currentState , originalState )
431
+ } catch ( predicateError ) {
432
+ runListener = false
447
433
448
- notifyListener ( entry , action , api , getOriginalState )
434
+ safelyNotifyError ( onError , predicateError , {
435
+ raisedBy : 'predicate' ,
436
+ } )
437
+ }
438
+
439
+ if ( ! runListener ) {
440
+ continue
441
+ }
442
+
443
+ notifyListener ( entry , action , api , getOriginalState )
444
+ }
449
445
}
446
+ } finally {
447
+ // Remove `originalState` store from this scope.
448
+ originalState = INTERNAL_NIL_TOKEN
450
449
}
451
- } finally {
452
- // Remove `originalState` store from this scope.
453
- originalState = INTERNAL_NIL_TOKEN
454
- }
455
450
456
- return result
457
- }
451
+ return result
452
+ }
458
453
459
- return assign (
454
+ return {
460
455
middleware,
461
- {
462
- addListener : addListener as TypedAddListener < S , D > ,
463
- removeListener : removeListener as TypedRemoveListener < S , D > ,
464
- clearListeners : clearListenerMiddleware ,
465
- } ,
466
- { } as WithMiddlewareType < typeof middleware >
467
- )
456
+ startListening,
457
+ stopListening,
458
+ clearListeners : clearListenerMiddleware ,
459
+ } as ListenerMiddlewareInstance < S , D , ExtraArgument >
468
460
}
0 commit comments