fix(reactivity): scheduled effect should not execute if stopped

fix #910
This commit is contained in:
Evan You 2020-04-02 19:49:45 -04:00
parent 5c33776e67
commit 0764c33d3d
2 changed files with 40 additions and 22 deletions

View File

@ -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(() => {}, {

View File

@ -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,23 +75,12 @@ 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)
} as ReactiveEffect
effect._isEffect = true
effect.active = true
effect.raw = fn
effect.deps = []
effect.options = options
return effect
}
function run(effect: ReactiveEffect, fn: Function, args: unknown[]): unknown {
if (!effect.active) { if (!effect.active) {
return fn(...args) return options.scheduler ? undefined : fn(...args)
} }
if (!effectStack.includes(effect)) { if (!effectStack.includes(effect)) {
cleanup(effect) cleanup(effect)
@ -106,6 +95,13 @@ function run(effect: ReactiveEffect, fn: Function, args: unknown[]): unknown {
activeEffect = effectStack[effectStack.length - 1] activeEffect = effectStack[effectStack.length - 1]
} }
} }
} as ReactiveEffect
effect._isEffect = true
effect.active = true
effect.raw = fn
effect.deps = []
effect.options = options
return effect
} }
function cleanup(effect: ReactiveEffect) { function cleanup(effect: ReactiveEffect) {