Search code examples
javascriptsettimeout

Getting different results for setTimeout & setImmediate inside setTimeout


setImmediate(function () {
    console.log('setImmediate')
});

setTimeout(function () {
    console.log('setTimeout')
}, 0);

outputs

setTimeout
setImmediate

But, these two functions inside setTimeout outputs different results.

setTimeout(function () {
    setImmediate(function () {
        console.log('setImmediate')
    });

    setTimeout(function () {
        console.log('setTimeout')
    }, 0);
}, 0);

Output:

setImmediate
setTimeout

Solution

  • As we know the event loop looks like this-

    timers -> IO -> poll -> check ->close -> timers -> ...
    

    Timers: callbacks from setInterval or setTimeout IO callbacks: callbacks from I/O events Idle: used internally by Node between IO and Poll phases Poll: retrieve new I/O events Check: callbacks from setImmediate execute here Close: handle closed connections like sockets

    In the first Example -

    We can see setTimeout gets executed before the setImmediate because timer queue is placed before the check Queue.

    However in the second case -

    When the setTimeout gets executed it triggers another setTimeout and a setImmediate, Since the Check queue is placed after the timer queue, the Check queue of the same loop executes the setImmediate but the nested setTimeout gets scheduled for the next cycle.

    Which is why the code below is can also be used to run something regularly

    let timerId = setTimeout(function tick() {
      alert('tick');
      timerId = setTimeout(tick, 2000); // (*)
    }, 2000);
    

    It schedules the next call, right at the end of the first call, which basically registers the call of setTimeout for the next loop.