-import { queueJob, nextTick, queuePostFlushCb } from '../src/scheduler'
+import {
+ queueJob,
+ nextTick,
+ queuePostFlushCb,
+ invalidateJob
+} from '../src/scheduler'
describe('scheduler', () => {
it('nextTick', async () => {
expect(calls).toEqual(['job1', 'job2', 'cb1', 'cb2'])
})
})
+
+ test('invalidateJob', async () => {
+ const calls: string[] = []
+ const job1 = () => {
+ calls.push('job1')
+ invalidateJob(job2)
+ job2()
+ }
+ const job2 = () => {
+ calls.push('job2')
+ }
+ // queue both jobs
+ queueJob(job1)
+ queueJob(job2)
+ expect(calls).toEqual([])
+ await nextTick()
+ // job2 should be called only once
+ expect(calls).toEqual(['job1', 'job2'])
+ })
})
isFunction,
PatchFlags
} from '@vue/shared'
-import { queueJob, queuePostFlushCb, flushPostFlushCbs } from './scheduler'
+import {
+ queueJob,
+ queuePostFlushCb,
+ flushPostFlushCbs,
+ invalidateJob
+} from './scheduler'
import {
effect,
stop,
} else {
// normal update
instance.next = n2
+ // in case the child component is also queued, remove it to avoid
+ // double updating the same child component in the same flush.
+ invalidateJob(instance.update)
// instance.update is the reactive effect runner.
instance.update()
}
import { ErrorCodes, callWithErrorHandling } from './errorHandling'
import { isArray } from '@vue/shared'
-const queue: Function[] = []
+const queue: (Function | null)[] = []
const postFlushCbs: Function[] = []
const p = Promise.resolve()
}
}
+export function invalidateJob(job: () => void) {
+ const i = queue.indexOf(job)
+ if (i > -1) {
+ queue[i] = null
+ }
+}
+
export function queuePostFlushCb(cb: Function | Function[]) {
if (!isArray(cb)) {
postFlushCbs.push(cb)
seen = seen || new Map()
}
while ((job = queue.shift())) {
+ if (job === null) {
+ continue
+ }
if (__DEV__) {
checkRecursiveUpdates(seen!, job)
}