|
70 | 70 | } |
71 | 71 | } |
72 | 72 |
|
73 | | - tick(millis: number = 0): void { |
| 73 | + tick(millis: number = 0, doTick?: (elapsed: number) => void): void { |
74 | 74 | let finalTime = this._currentTime + millis; |
| 75 | + let lastCurrentTime = 0; |
| 76 | + if (this._schedulerQueue.length === 0 && doTick) { |
| 77 | + doTick(millis); |
| 78 | + return; |
| 79 | + } |
75 | 80 | while (this._schedulerQueue.length > 0) { |
76 | 81 | let current = this._schedulerQueue[0]; |
77 | 82 | if (finalTime < current.endTime) { |
|
80 | 85 | } else { |
81 | 86 | // Time to run scheduled function. Remove it from the head of queue. |
82 | 87 | let current = this._schedulerQueue.shift(); |
| 88 | + lastCurrentTime = this._currentTime; |
83 | 89 | this._currentTime = current.endTime; |
| 90 | + if (doTick) { |
| 91 | + doTick(this._currentTime - lastCurrentTime); |
| 92 | + } |
84 | 93 | let retval = current.func.apply(global, current.args); |
85 | 94 | if (!retval) { |
86 | 95 | // Uncaught exception in the current scheduled function. Stop processing the queue. |
|
91 | 100 | this._currentTime = finalTime; |
92 | 101 | } |
93 | 102 |
|
94 | | - flush(limit = 20, flushPeriodic = false, tick?: (elapsed: number) => void): number { |
| 103 | + flush(limit = 20, flushPeriodic = false, doTick?: (elapsed: number) => void): number { |
| 104 | + if (flushPeriodic) { |
| 105 | + return this.flushPeriodic(doTick); |
| 106 | + } else { |
| 107 | + return this.flushNonPeriodic(limit, doTick); |
| 108 | + } |
| 109 | + } |
| 110 | + |
| 111 | + private flushPeriodic(doTick?: (elapsed: number) => void): number { |
| 112 | + if (this._schedulerQueue.length === 0) { |
| 113 | + return 0; |
| 114 | + } |
| 115 | + // Find the last task currently queued in the scheduler queue and tick |
| 116 | + // till that time. |
| 117 | + const startTime = this._currentTime; |
| 118 | + const lastTask = this._schedulerQueue[this._schedulerQueue.length - 1]; |
| 119 | + this.tick(lastTask.endTime - startTime, doTick); |
| 120 | + return this._currentTime - startTime; |
| 121 | + } |
| 122 | + |
| 123 | + private flushNonPeriodic(limit: number, doTick?: (elapsed: number) => void): number { |
95 | 124 | const startTime = this._currentTime; |
96 | | - let lastCurrentTime = this._currentTime; |
| 125 | + let lastCurrentTime = 0; |
97 | 126 | let count = 0; |
98 | | - const seenTimers: number[] = []; |
99 | 127 | while (this._schedulerQueue.length > 0) { |
100 | 128 | count++; |
101 | 129 | if (count > limit) { |
102 | 130 | throw new Error( |
103 | 131 | 'flush failed after reaching the limit of ' + limit + |
104 | 132 | ' tasks. Does your code use a polling timeout?'); |
105 | 133 | } |
106 | | - if (!flushPeriodic) { |
107 | | - // flush only non-periodic timers. |
108 | | - // If the only remaining tasks are periodic(or requestAnimationFrame), finish flushing. |
109 | | - if (this._schedulerQueue.filter(task => !task.isPeriodic && !task.isRequestAnimationFrame) |
110 | | - .length === 0) { |
111 | | - break; |
112 | | - } |
113 | | - } else { |
114 | | - // flushPeriodic has been requested. |
115 | | - // Stop when all timer id-s have been seen at least once. |
116 | | - if (this._schedulerQueue |
117 | | - .filter( |
118 | | - task => |
119 | | - seenTimers.indexOf(task.id) === -1 || this._currentTime === task.endTime) |
120 | | - .length === 0) { |
121 | | - break; |
122 | | - } |
| 134 | + |
| 135 | + // flush only non-periodic timers. |
| 136 | + // If the only remaining tasks are periodic(or requestAnimationFrame), finish flushing. |
| 137 | + if (this._schedulerQueue.filter(task => !task.isPeriodic && !task.isRequestAnimationFrame) |
| 138 | + .length === 0) { |
| 139 | + break; |
123 | 140 | } |
| 141 | + |
124 | 142 | const current = this._schedulerQueue.shift(); |
125 | | - if (seenTimers.indexOf(current.id) === -1) { |
126 | | - seenTimers.push(current.id); |
127 | | - } |
128 | 143 | lastCurrentTime = this._currentTime; |
129 | 144 | this._currentTime = current.endTime; |
130 | | - if (tick) { |
131 | | - // Tick any secondary schedulers like Jasmine mock Date. |
132 | | - tick(this._currentTime - lastCurrentTime); |
| 145 | + if (doTick) { |
| 146 | + // Update any secondary schedulers like Jasmine mock Date. |
| 147 | + doTick(this._currentTime - lastCurrentTime); |
133 | 148 | } |
134 | 149 | const retval = current.func.apply(global, current.args); |
135 | 150 | if (!retval) { |
|
253 | 268 | throw error; |
254 | 269 | } |
255 | 270 |
|
256 | | - tick(millis: number = 0): void { |
| 271 | + tick(millis: number = 0, doTick?: (elapsed: number) => void): void { |
257 | 272 | FakeAsyncTestZoneSpec.assertInZone(); |
258 | 273 | this.flushMicrotasks(); |
259 | | - this._scheduler.tick(millis); |
| 274 | + this._scheduler.tick(millis, doTick); |
260 | 275 | if (this._lastError !== null) { |
261 | 276 | this._resetLastErrorAndThrow(); |
262 | 277 | } |
|
277 | 292 | flushErrors(); |
278 | 293 | } |
279 | 294 |
|
280 | | - flush(limit?: number, flushPeriodic?: boolean, tick?: (elapsed: number) => void): number { |
| 295 | + flush(limit?: number, flushPeriodic?: boolean, doTick?: (elapsed: number) => void): number { |
281 | 296 | FakeAsyncTestZoneSpec.assertInZone(); |
282 | 297 | this.flushMicrotasks(); |
283 | | - const elapsed = this._scheduler.flush(limit, flushPeriodic, tick); |
| 298 | + const elapsed = this._scheduler.flush(limit, flushPeriodic, doTick); |
284 | 299 | if (this._lastError !== null) { |
285 | 300 | this._resetLastErrorAndThrow(); |
286 | 301 | } |
|
0 commit comments