NodeJS - setTimeout(fn,0) vs setImmediate(fn)

Javascriptnode.js

Javascript Problem Overview


What is the difference between those two, and when will I use one over the other?

Javascript Solutions


Solution 1 - Javascript

setTimeout is simply like calling the function after delay has finished. Whenever a function is called it is not executed immediately, but queued so that it is executed after all the executing and currently queued eventhandlers finish first. setTimeout(,0) essentially means execute after all current functions in the present queue get executed. No guarantees can be made about how long it could take.

setImmediate is similar in this regard except that it doesn't use queue of functions. It checks queue of I/O eventhandlers. If all I/O events in the current snapshot are processed, it executes the callback. It queues them immediately after the last I/O handler somewhat like process.nextTick. So it is faster.

Also (setTimeout,0) will be slow because it will check the timer at least once before executing. At times it can be twice as slow. Here is a benchmark.

var Suite = require('benchmark').Suite
var fs = require('fs')

var suite = new Suite

suite.add('deffered.resolve()', function(deferred) {
  deferred.resolve()
}, {defer: true})

suite.add('setImmediate()', function(deferred) {
  setImmediate(function() {
    deferred.resolve()
  })
}, {defer: true})

suite.add('setTimeout(,0)', function(deferred) {
  setTimeout(function() {
    deferred.resolve()
  },0)
}, {defer: true})

suite
.on('cycle', function(event) {
  console.log(String(event.target));
})
.on('complete', function() {
  console.log('Fastest is ' + this.filter('fastest').pluck('name'));
})
.run({async: true})

Output

deffered.resolve() x 993 ops/sec ±0.67% (22 runs sampled)
setImmediate() x 914 ops/sec ±2.48% (57 runs sampled)
setTimeout(,0) x 445 ops/sec ±2.79% (82 runs sampled)

First one gives idea of fastest possible calls. You can check yourself if setTimeout gets called half as many times as other. Also remember setImmediate will adjust to your filesystem calls. So under load it will perform less. I don't think setTimeout can do better.

setTimeout is un-intrusive way of calling functions after some time. Its just like its in the browser. It may not be suited for server-side (think why I used benchmark.js not setTimeout).

Solution 2 - Javascript

A great article about how event loop works and clears some misconceptions. http://voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout/

Citing the article:

setImmediate callbacks are called after I/O Queue callbacks are finished or timed out. setImmediate callbacks are placed in Check Queue, which are processed after I/O Queue.

setTimeout(fn, 0) callbacks are placed in Timer Queue and will be called after I/O callbacks as well as Check Queue callbacks. As event loop, process the timer queue first in each iteration, so which one will be executed first depends on which phase event loop is.

Solution 3 - Javascript

setImmediate() is to schedule the immediate execution of callback after I/O events callbacks and before setTimeout and setInterval .

setTimeout() is to schedule execution of a one-time callback after delay milliseconds.

This is what the documents say.

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

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

If you run the above code, the result will be like this... even though the current doc states that "To schedule the "immediate" execution of callback after I/O events callbacks and before setTimeout and setInterval." ..

Result.. > setTimeout > > setImmediate

If you wrap your example in another timer, it always prints setImmediate followed by setTimeout.

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

Solution 4 - Javascript

always use setImmediate, unless you are really sure that you need setTimeout(,0) (but I can't even imagine, what for). setImmediate callback will almost always be executed before setTimeout(,0), except when called in first tick and in setImmediate callback.

Solution 5 - Javascript

setTimeout(fn,0) can be used for preventing the browser from freezing in massive update. for example in websocket.onmessage, you may have html changes, and if messages keep coming, the browser may freeze when using setImmidiate

Solution 6 - Javascript

I think the answer of Navya S is not correct, here is my test code:

let set = new Set();

function orderTest() {
  let seq = [];
  let add = () => set.add(seq.join());
  setTimeout(function () {
    setTimeout(function () {
      seq.push('setTimeout');
      if (seq.length === 2) add();
    }, 0);

    setImmediate(function () {
      seq.push('setImmediate');
      if (seq.length === 2) add();
    });
  }, 10);
}

// loop 100 times
for (let i = 0; i < 100; i++) {
  orderTest();
}

setTimeout(() => {
  // will print one or two items, it's random
  for (item of set) {
    console.log(item);
  }
}, 100);

The explanations is here

Solution 7 - Javascript

To understand them deeply please once go through the event loop phases.

SetImmediate: It gets executed in the "check" phase. The check phase is called after the I/O phase.

SetTimeOut: It gets executed in the "timer" phase. The timer phase is the first phase but is called after the I/O phase as well as the Check phase.

To get the output in a deterministic manner, it will depend on which phase the event-loop is; accordingly, we can use the function out of two.

Solution 8 - Javascript

When the Javascript engine starts execution, It checks code line by line.

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

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

When it comes to

settimeout, it moves from call-stack to call queue and starts a timer for execution.

setimmediate, it moves from call-stack to micro-queue(which is start execution immediately after the first loop is complete)

So, if settimeout value is 0, it will complete its timer before call-stack loop complete.

that's why, settimeout will print before setimmediate.

Now, suppose

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

This means, first main timeout move to call-queue. meanwhile, call-stack complete its execution.

So, after 10ms, function comes to call stack, it will direct execute setimmediate. Because call-stack is already free to execute task.

Solution 9 - Javascript

use setImmediate() for not blocking the event loop. The callback will run on the next event loop, as soon as the current one is done.

use setTimeout() for controlled delays. The function will run after the specified delay. The minimum delay is 1 millisecond.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionShlomi SchwartzView Question on Stackoverflow
Solution 1 - Javascriptuser568109View Answer on Stackoverflow
Solution 2 - JavascriptAman GuptaView Answer on Stackoverflow
Solution 3 - JavascriptNavya SView Answer on Stackoverflow
Solution 4 - JavascriptvkurchatkinView Answer on Stackoverflow
Solution 5 - JavascriptLior GoldembergView Answer on Stackoverflow
Solution 6 - Javascript笑笑十年View Answer on Stackoverflow
Solution 7 - JavascriptKanika SharmaView Answer on Stackoverflow
Solution 8 - JavascriptHardik MandankaaView Answer on Stackoverflow
Solution 9 - JavascriptAndrasView Answer on Stackoverflow