Skip to content

Commit 8c32459

Browse files
committed
Optimize publishing size
- Used `Object.assign()` to avoid a helper function being added - Rewrote `createListener` logic to shrink code - Tweaked TaskAbortError for size
1 parent c4e18b3 commit 8c32459

File tree

3 files changed

+59
-54
lines changed

3 files changed

+59
-54
lines changed
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
export class TaskAbortError implements Error {
2-
name: string
3-
message: string
4-
constructor(public reason?: string) {
5-
this.name = 'TaskAbortError'
6-
this.message = `task cancelled` + (reason != null ? `: "${reason}"` : '')
2+
name = 'TaskAbortError'
3+
message = ''
4+
constructor(public reason = 'unknown') {
5+
this.message = `task cancelled (reason: ${reason})`
76
}
87
}

packages/action-listener-middleware/src/index.ts

Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,14 @@ export type {
6565
TaskResult,
6666
} from './types'
6767

68-
const defaultWhen: MiddlewarePhase = 'afterReducer'
69-
const actualMiddlewarePhases = ['beforeReducer', 'afterReducer'] as const
68+
//Overly-aggressive byte-shaving
69+
const { assign } = Object
70+
71+
const beforeReducer = 'beforeReducer' as const
72+
const afterReducer = 'afterReducer' as const
73+
74+
const defaultWhen: MiddlewarePhase = afterReducer
75+
const actualMiddlewarePhases = [beforeReducer, afterReducer] as const
7076

7177
const createFork = (parentAbortSignal: AbortSignal) => {
7278
return <T>(taskExecutor: ForkedTaskExecutor<T>): ForkedTask<T> => {
@@ -162,19 +168,17 @@ const createTakePattern = <S>(
162168
export const createListenerEntry: TypedCreateListenerEntry<unknown> = (
163169
options: FallbackAddListenerOptions
164170
) => {
165-
let predicate: ListenerPredicate<any, any>
166-
let type: string | undefined
167-
168-
if ('type' in options) {
169-
type = options.type
170-
predicate = (action: any): action is any => action.type === type
171-
} else if ('actionCreator' in options) {
172-
type = options.actionCreator!.type
173-
predicate = options.actionCreator.match
174-
} else if ('matcher' in options) {
175-
predicate = options.matcher
176-
} else if ('predicate' in options) {
177-
predicate = options.predicate
171+
let { type, actionCreator, matcher, predicate, listener } = options
172+
173+
if (type) {
174+
predicate = createAction(type).match
175+
} else if (actionCreator) {
176+
type = actionCreator!.type
177+
predicate = actionCreator.match
178+
} else if (matcher) {
179+
predicate = matcher
180+
} else if (predicate) {
181+
// pass
178182
} else {
179183
throw new Error(
180184
'Creating a listener requires one of the known fields for matching against actions'
@@ -185,7 +189,7 @@ export const createListenerEntry: TypedCreateListenerEntry<unknown> = (
185189
const entry: ListenerEntry<unknown> = {
186190
when: options.when || defaultWhen,
187191
id,
188-
listener: options.listener,
192+
listener,
189193
type,
190194
predicate,
191195
pendingSet: new Set<AbortController>(),
@@ -371,30 +375,33 @@ export function createActionListenerMiddleware<
371375
try {
372376
entry.pendingSet.add(internalTaskController)
373377
await Promise.resolve(
374-
entry.listener(action, {
375-
...api,
376-
getOriginalState,
377-
condition,
378-
take,
379-
delay,
380-
pause,
381-
currentPhase,
382-
extra,
383-
signal: internalTaskController.signal,
384-
fork,
385-
unsubscribe: entry.unsubscribe,
386-
subscribe: () => {
387-
listenerMap.set(entry.id, entry)
388-
},
389-
cancelPrevious: () => {
390-
entry.pendingSet.forEach((controller, _, set) => {
391-
if (controller !== internalTaskController) {
392-
controller.abort()
393-
set.delete(controller)
394-
}
395-
})
396-
},
397-
})
378+
entry.listener(
379+
action,
380+
// Use assign() rather than ... to avoid extra helper functions added to bundle
381+
assign({}, api, {
382+
getOriginalState,
383+
condition,
384+
take,
385+
delay,
386+
pause,
387+
currentPhase,
388+
extra,
389+
signal: internalTaskController.signal,
390+
fork,
391+
unsubscribe: entry.unsubscribe,
392+
subscribe: () => {
393+
listenerMap.set(entry.id, entry)
394+
},
395+
cancelPrevious: () => {
396+
entry.pendingSet.forEach((controller, _, set) => {
397+
if (controller !== internalTaskController) {
398+
controller.abort()
399+
set.delete(controller)
400+
}
401+
})
402+
},
403+
})
404+
)
398405
)
399406
} catch (listenerError) {
400407
if (!(listenerError instanceof TaskAbortError)) {
@@ -467,15 +474,15 @@ export function createActionListenerMiddleware<
467474

468475
notifyListener(entry, action, api, getOriginalState, currentPhase)
469476
}
470-
if (currentPhase === 'beforeReducer') {
477+
if (currentPhase === beforeReducer) {
471478
result = next(action)
472479
} else {
473480
return result
474481
}
475482
}
476483
}
477484

478-
return Object.assign(
485+
return assign(
479486
middleware,
480487
{
481488
addListener,

packages/action-listener-middleware/src/types.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -373,13 +373,12 @@ export type WithMiddlewareType<T extends Middleware<any, any, any>> = {
373373
}
374374

375375
// A shorthand form of the accepted args, solely so that `createListenerEntry` has validly-typed conditional logic when checking the options contents
376-
export type FallbackAddListenerOptions = (
377-
| { actionCreator: TypedActionCreator<string> }
378-
| { type: string }
379-
| { matcher: MatchFunction<any> }
380-
| { predicate: ListenerPredicate<any, any> }
381-
) &
382-
ActionListenerOptions & { listener: ActionListener<any, any, any> }
376+
export type FallbackAddListenerOptions = {
377+
actionCreator?: TypedActionCreator<string>
378+
type?: string
379+
matcher?: MatchFunction<any>
380+
predicate?: ListenerPredicate<any, any>
381+
} & ActionListenerOptions & { listener: ActionListener<any, any, any> }
383382

384383
/**
385384
* Utility Types

0 commit comments

Comments
 (0)