What is the difference between those two, and when will I use one over the other?
问题:
回答1:
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 immedieately 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
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).
回答2:
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);
回答3:
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.
回答4:
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.
回答5:
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
回答6:
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
回答7:
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.