fix(reactivity): scheduled effect should not execute if stopped
fix #910
This commit is contained in:
parent
5c33776e67
commit
0764c33d3d
@ -678,6 +678,28 @@ describe('reactivity/effect', () => {
|
|||||||
expect(dummy).toBe(3)
|
expect(dummy).toBe(3)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('stop with scheduler', () => {
|
||||||
|
let dummy
|
||||||
|
const obj = reactive({ prop: 1 })
|
||||||
|
const queue: (() => void)[] = []
|
||||||
|
const runner = effect(
|
||||||
|
() => {
|
||||||
|
dummy = obj.prop
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scheduler: e => queue.push(e)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
obj.prop = 2
|
||||||
|
expect(dummy).toBe(1)
|
||||||
|
expect(queue.length).toBe(1)
|
||||||
|
stop(runner)
|
||||||
|
|
||||||
|
// a scheduled effect should not execute anymore after stopped
|
||||||
|
queue.forEach(e => e())
|
||||||
|
expect(dummy).toBe(1)
|
||||||
|
})
|
||||||
|
|
||||||
it('events: onStop', () => {
|
it('events: onStop', () => {
|
||||||
const onStop = jest.fn()
|
const onStop = jest.fn()
|
||||||
const runner = effect(() => {}, {
|
const runner = effect(() => {}, {
|
||||||
|
@ -10,7 +10,7 @@ type KeyToDepMap = Map<any, Dep>
|
|||||||
const targetMap = new WeakMap<any, KeyToDepMap>()
|
const targetMap = new WeakMap<any, KeyToDepMap>()
|
||||||
|
|
||||||
export interface ReactiveEffect<T = any> {
|
export interface ReactiveEffect<T = any> {
|
||||||
(): T
|
(...args: any[]): T
|
||||||
_isEffect: true
|
_isEffect: true
|
||||||
active: boolean
|
active: boolean
|
||||||
raw: () => T
|
raw: () => T
|
||||||
@ -75,11 +75,26 @@ export function stop(effect: ReactiveEffect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createReactiveEffect<T = any>(
|
function createReactiveEffect<T = any>(
|
||||||
fn: () => T,
|
fn: (...args: any[]) => T,
|
||||||
options: ReactiveEffectOptions
|
options: ReactiveEffectOptions
|
||||||
): ReactiveEffect<T> {
|
): ReactiveEffect<T> {
|
||||||
const effect = function reactiveEffect(...args: unknown[]): unknown {
|
const effect = function reactiveEffect(...args: unknown[]): unknown {
|
||||||
return run(effect, fn, args)
|
if (!effect.active) {
|
||||||
|
return options.scheduler ? undefined : fn(...args)
|
||||||
|
}
|
||||||
|
if (!effectStack.includes(effect)) {
|
||||||
|
cleanup(effect)
|
||||||
|
try {
|
||||||
|
enableTracking()
|
||||||
|
effectStack.push(effect)
|
||||||
|
activeEffect = effect
|
||||||
|
return fn(...args)
|
||||||
|
} finally {
|
||||||
|
effectStack.pop()
|
||||||
|
resetTracking()
|
||||||
|
activeEffect = effectStack[effectStack.length - 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
} as ReactiveEffect
|
} as ReactiveEffect
|
||||||
effect._isEffect = true
|
effect._isEffect = true
|
||||||
effect.active = true
|
effect.active = true
|
||||||
@ -89,25 +104,6 @@ function createReactiveEffect<T = any>(
|
|||||||
return effect
|
return effect
|
||||||
}
|
}
|
||||||
|
|
||||||
function run(effect: ReactiveEffect, fn: Function, args: unknown[]): unknown {
|
|
||||||
if (!effect.active) {
|
|
||||||
return fn(...args)
|
|
||||||
}
|
|
||||||
if (!effectStack.includes(effect)) {
|
|
||||||
cleanup(effect)
|
|
||||||
try {
|
|
||||||
enableTracking()
|
|
||||||
effectStack.push(effect)
|
|
||||||
activeEffect = effect
|
|
||||||
return fn(...args)
|
|
||||||
} finally {
|
|
||||||
effectStack.pop()
|
|
||||||
resetTracking()
|
|
||||||
activeEffect = effectStack[effectStack.length - 1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function cleanup(effect: ReactiveEffect) {
|
function cleanup(effect: ReactiveEffect) {
|
||||||
const { deps } = effect
|
const { deps } = effect
|
||||||
if (deps.length) {
|
if (deps.length) {
|
||||||
|
Loading…
Reference in New Issue
Block a user