requestAnimationFrame always called first
tested on:
- chrome 80
- firefox 70
- safari 13
requestAnimationFrame sometimes called first
tested on:
- chrome 80
| function slowOp(factor) { | |
| const n = 999999 * factor; | |
| let i = -1; | |
| while (++i < n) { | |
| Math.pow(23, i % 3); | |
| } | |
| } | |
| function runTimers({timeoutInterval, shouldNest}) { | |
| return new Promise(resolve => { | |
| let timeoutCalled | |
| let requestAnimationFrameCalled; | |
| setTimeout(onTimeout, timeoutInterval); | |
| if (shouldNest) { | |
| requestAnimationFrame(() => requestAnimationFrame(onAnimationFrame)); | |
| } else { | |
| requestAnimationFrame(onAnimationFrame); | |
| } | |
| function onAnimationFrame() { | |
| if (timeoutCalled) { | |
| console.log('requestAnimationFrame called **after** timeout'); | |
| } else { | |
| console.log('requestAnimationFrame called **before** timeout'); | |
| } | |
| requestAnimationFrameCalled = true; | |
| maybeResolve(); | |
| } | |
| function onTimeout() { | |
| timeoutCalled = true | |
| maybeResolve(); | |
| } | |
| function maybeResolve() { | |
| if (timeoutCalled && requestAnimationFrameCalled) { | |
| resolve(); | |
| } | |
| } | |
| }); | |
| } | |
| async function runOnce(opts) { | |
| const { slowdownFactor } = opts; | |
| let done | |
| runTimers(opts).then(() => done = true); | |
| while (!done) { | |
| await new Promise(resolve => setTimeout(resolve, 0)); | |
| slowOp(slowdownFactor); | |
| } | |
| } | |
| async function run(opts) { | |
| let i = -1; | |
| while (++i < opts.n) await runOnce(opts); | |
| } | |
| run({ | |
| n: 10, | |
| timeoutInterval: 20, | |
| slowdownFactor: 1000, | |
| shouldNest: false | |
| }); |