Skip to content

Commit

Permalink
feat: middleware in baseWatch
Browse files Browse the repository at this point in the history
  • Loading branch information
LittleSound committed Jan 13, 2024
1 parent 2fdda65 commit 60a1b97
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 24 deletions.
78 changes: 78 additions & 0 deletions packages/reactivity/__tests__/baseWatch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,82 @@ describe('baseWatch', () => {
scope.stop()
expect(calls).toEqual(['sync 2', 'post 2'])
})
test('baseWatch with middleware', async () => {
let effectCalls: string[] = []
let watchCalls: string[] = []
const source = ref(0)

// effect
baseWatch(
() => {
source.value
effectCalls.push('effect')
onEffectCleanup(() => effectCalls.push('effect cleanup'))
},
null,
{
scheduler,
middleware: next => {
effectCalls.push('before effect running')
next()
effectCalls.push('effect ran')
},
},
)
// watch
baseWatch(
() => source.value,
() => {
watchCalls.push('watch')
onEffectCleanup(() => watchCalls.push('watch cleanup'))
},
{
scheduler,
middleware: next => {
watchCalls.push('before watch running')
next()
watchCalls.push('watch ran')
},
},
)

expect(effectCalls).toEqual([])
expect(watchCalls).toEqual([])
await nextTick()
expect(effectCalls).toEqual([
'before effect running',
'effect',
'effect ran',
])
expect(watchCalls).toEqual([])
effectCalls.length = 0
watchCalls.length = 0

source.value++
await nextTick()
expect(effectCalls).toEqual([
'before effect running',
'effect cleanup',
'effect',
'effect ran',
])
expect(watchCalls).toEqual(['before watch running', 'watch', 'watch ran'])
effectCalls.length = 0
watchCalls.length = 0

source.value++
await nextTick()
expect(effectCalls).toEqual([
'before effect running',
'effect cleanup',
'effect',
'effect ran',
])
expect(watchCalls).toEqual([
'before watch running',
'watch cleanup',
'watch',
'watch ran',
])
})
})
62 changes: 38 additions & 24 deletions packages/reactivity/src/baseWatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export interface BaseWatchOptions<Immediate = boolean> extends DebuggerOptions {
deep?: boolean
once?: boolean
scheduler?: Scheduler
middleware?: BaseWatchMiddleware
onError?: HandleError
onWarn?: HandleWarn
}
Expand All @@ -83,6 +84,7 @@ export type Scheduler = (
effect: ReactiveEffect,
isInit: boolean,
) => void
export type BaseWatchMiddleware = (next: () => unknown) => any
export type HandleError = (err: unknown, type: BaseWatchErrorCodes) => void
export type HandleWarn = (msg: string, ...args: any[]) => void

Expand Down Expand Up @@ -132,6 +134,7 @@ export function baseWatch(
scheduler = DEFAULT_SCHEDULER,
onWarn = __DEV__ ? warn : NOOP,
onError = DEFAULT_HANDLE_ERROR,
middleware,
onTrack,
onTrigger,
}: BaseWatchOptions = EMPTY_OBJ,
Expand Down Expand Up @@ -211,6 +214,10 @@ export function baseWatch(
activeEffect = currentEffect
}
}
if (middleware) {
const baseGetter = getter
getter = () => middleware(baseGetter)
}
}
} else {
getter = NOOP
Expand Down Expand Up @@ -264,31 +271,38 @@ export function baseWatch(
? (newValue as any[]).some((v, i) => hasChanged(v, oldValue[i]))
: hasChanged(newValue, oldValue))
) {
// cleanup before running cb again
if (cleanup) {
cleanup()
const next = () => {
// cleanup before running cb again
if (cleanup) {
cleanup()
}
const currentEffect = activeEffect
activeEffect = effect
try {
callWithAsyncErrorHandling(
cb!,
onError,
BaseWatchErrorCodes.WATCH_CALLBACK,
[
newValue,
// pass undefined as the old value when it's changed for the first time
oldValue === INITIAL_WATCHER_VALUE
? undefined
: isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE
? []
: oldValue,
onEffectCleanup,
],
)
oldValue = newValue
} finally {
activeEffect = currentEffect
}
}
const currentEffect = activeEffect
activeEffect = effect
try {
callWithAsyncErrorHandling(
cb,
onError,
BaseWatchErrorCodes.WATCH_CALLBACK,
[
newValue,
// pass undefined as the old value when it's changed for the first time
oldValue === INITIAL_WATCHER_VALUE
? undefined
: isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE
? []
: oldValue,
onEffectCleanup,
],
)
oldValue = newValue
} finally {
activeEffect = currentEffect
if (middleware) {
middleware(next)
} else {
next()
}
}
} else {
Expand Down
1 change: 1 addition & 0 deletions packages/reactivity/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,6 @@ export {
traverse,
BaseWatchErrorCodes,
type BaseWatchOptions,
type BaseWatchMiddleware,
type Scheduler,
} from './baseWatch'

0 comments on commit 60a1b97

Please sign in to comment.