fix(scheduler): ensure updates are always inserted in ascending id order (#3184)
fix #2768, fix #2829
This commit is contained in:
@@ -57,6 +57,25 @@ export function nextTick(
|
||||
return fn ? p.then(this ? fn.bind(this) : fn) : p
|
||||
}
|
||||
|
||||
// #2768
|
||||
// Use binary-search to find a suitable position in the queue,
|
||||
// so that the queue maintains the increasing order of job's id,
|
||||
// which can prevent the job from being skipped and also can avoid repeated patching.
|
||||
function findInsertionIndex(job: SchedulerJob) {
|
||||
// the start index should be `flushIndex + 1`
|
||||
let start = flushIndex + 1
|
||||
let end = queue.length
|
||||
const jobId = getId(job)
|
||||
|
||||
while (start < end) {
|
||||
const middle = (start + end) >>> 1
|
||||
const middleJobId = getId(queue[middle])
|
||||
middleJobId < jobId ? (start = middle + 1) : (end = middle)
|
||||
}
|
||||
|
||||
return start
|
||||
}
|
||||
|
||||
export function queueJob(job: SchedulerJob) {
|
||||
// the dedupe search uses the startIndex argument of Array.includes()
|
||||
// by default the search index includes the current job that is being run
|
||||
@@ -72,7 +91,12 @@ export function queueJob(job: SchedulerJob) {
|
||||
)) &&
|
||||
job !== currentPreFlushParentJob
|
||||
) {
|
||||
queue.push(job)
|
||||
const pos = findInsertionIndex(job)
|
||||
if (pos > -1) {
|
||||
queue.splice(pos, 0, job)
|
||||
} else {
|
||||
queue.push(job)
|
||||
}
|
||||
queueFlush()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user