File tree 2 files changed +57
-1
lines changed
2 files changed +57
-1
lines changed Original file line number Diff line number Diff line change @@ -44,6 +44,38 @@ describe('scheduler', () => {
44
44
expect ( calls ) . toEqual ( [ 'job1' , 'job2' ] )
45
45
} )
46
46
47
+ it ( "should insert jobs in ascending order of job's id when flushing" , async ( ) => {
48
+ const calls : string [ ] = [ ]
49
+ const job1 = ( ) => {
50
+ calls . push ( 'job1' )
51
+
52
+ queueJob ( job2 )
53
+ queueJob ( job3 )
54
+ queueJob ( job4 )
55
+ }
56
+
57
+ const job2 = ( ) => {
58
+ calls . push ( 'job2' )
59
+ }
60
+ job2 . id = 10
61
+
62
+ const job3 = ( ) => {
63
+ calls . push ( 'job3' )
64
+ }
65
+ job3 . id = 1
66
+
67
+ // job4 gets the Infinity as it's id
68
+ const job4 = ( ) => {
69
+ calls . push ( 'job4' )
70
+ }
71
+
72
+ queueJob ( job1 )
73
+
74
+ expect ( calls ) . toEqual ( [ ] )
75
+ await nextTick ( )
76
+ expect ( calls ) . toEqual ( [ 'job1' , 'job3' , 'job2' , 'job4' ] )
77
+ } )
78
+
47
79
it ( 'should dedupe queued jobs' , async ( ) => {
48
80
const calls : string [ ] = [ ]
49
81
const job1 = ( ) => {
Original file line number Diff line number Diff line change @@ -57,6 +57,25 @@ export function nextTick(
57
57
return fn ? p . then ( this ? fn . bind ( this ) : fn ) : p
58
58
}
59
59
60
+ // #2768
61
+ // Use binary-search to find a suitable position in the queue,
62
+ // so that the queue maintains the increasing order of job's id,
63
+ // which can prevent the job from being skipped and also can avoid repeated patching.
64
+ function findInsertionIndex ( job : SchedulerJob ) {
65
+ // the start index should be `flushIndex + 1`
66
+ let start = flushIndex + 1
67
+ let end = queue . length
68
+ const jobId = getId ( job )
69
+
70
+ while ( start < end ) {
71
+ const middle = ( start + end ) >>> 1
72
+ const middleJobId = getId ( queue [ middle ] )
73
+ middleJobId < jobId ? ( start = middle + 1 ) : ( end = middle )
74
+ }
75
+
76
+ return start
77
+ }
78
+
60
79
export function queueJob ( job : SchedulerJob ) {
61
80
// the dedupe search uses the startIndex argument of Array.includes()
62
81
// by default the search index includes the current job that is being run
@@ -72,7 +91,12 @@ export function queueJob(job: SchedulerJob) {
72
91
) ) &&
73
92
job !== currentPreFlushParentJob
74
93
) {
75
- queue . push ( job )
94
+ const pos = findInsertionIndex ( job )
95
+ if ( pos > - 1 ) {
96
+ queue . splice ( pos , 0 , job )
97
+ } else {
98
+ queue . push ( job )
99
+ }
76
100
queueFlush ( )
77
101
}
78
102
}
You can’t perform that action at this time.
0 commit comments