|
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