console.log('script start');
const interval = setInterval(() => {
console.log('setInterval');
}, 0);
setTimeout(() => {
console.log('setTimeout 1');
Promise.resolve().then(() => {
console.log('promise 3');
}).then(() => {
console.log('promise 4');
}).then(() => {
setTimeout(() => {
console.log('setTimeout 2');
Promise.resolve().then(() => {
console.log('promise 5');
}).then(() => {
console.log('promise 6');
}).then(() => {
clearInterval(interval);
});
}, 0);
});
}, 0);
Promise.resolve().then(() => {
console.log('promise 1');
}).then(() => {
console.log('promise 2');
});
-----
If I paste the above into the console, I get:
promise 1
promise 2
setInterval
setTimeout 1
promise 3
promise 4
setInterval
setInterval
setTimeout 2
promise 5
promise 6
Those two setIntervals in a row look like a spec violation. It may also be a race condition, but it shouldn't be.
Ignoring the microtasks (although they seem to be required to reproduce the issue), here's how things should happen:
Script executes, logs 'script start'. Task list:
* set interval task
* set timeout 1 task
Interval runs, logs 'setInterval', and requeues itself. Task list:
* set timeout 1 task
* set interval task
Timeout runs, logs 'setTimeout 1', and queues another timeout. Task list:
* set interval task
* set timeout 2 task
Interval runs, logs 'setInterval', and requeues itself. Task list:
* set timeout 2 task
* set interval task
^ This seems to be where things go wrong. The next interval task somehow happens before the next timeout task.
Timeout runs, logs 'setTimeout 2', and clears the interval. Task list:
* set interval task
Interval task runs, but exits before the callback because it's been cleared.
Although both setTimeout and setInterval may 'wait' a user-agent defined time before queueing a task, it mustn't result in callbacks happening in a different order from when they were scheduled (if the timeout is the same). From the spec: Wait until any invocations of this algorithm that had the same method context, that started before this one, and whose timeout is equal to or less than this one's, have completed. https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialisation-steps
Comment 1 by altimin@chromium.org
, Apr 3 2018