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

Shl*_*rtz 72 javascript node.js

这两者有什么区别,我什么时候才能使用另一个?

use*_*109 66

setTimeout就像在延迟完成后调用函数一样.每当调用一个函数时,它不会立即执行,而是排队,以便在所有执行和当前排队的事件处理程序首先完成后执行.setTimeout(,0)实质上是指在执行当前队列中的所有当前函数之后执行.不能保证可以花多长时间.

setImmediate在这方面类似,只是它不使用函数队列.它检查I/O事件处理程序的队列.如果处理了当前快照中的所有I/O事件,它将执行回调.在最后一个I/O处理程序有点像process.nextTick之后,它会立即对它们进行排队.所以它更快.

此外(setTimeout,0)将很慢,因为它将在执行前至少检查一次定时器.有时它可能慢两倍.这是一个基准.

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})
Run Code Online (Sandbox Code Playgroud)

产量

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)
Run Code Online (Sandbox Code Playgroud)

第一个给出了最快可能的呼叫的想法.你可以检查自己setTimeout被调用的次数是其他的一半.还记得setImmediate会调整你的文件系统调用.所以在负载下它会表现得更少.我不认为setTimeout可以做得更好.

setTimeout是一段时间后调用函数的非侵入式方法.就像它在浏览器中一样.它可能不适合服务器端(想想我为什么使用benchmark.js而不是setTimeout).

  • 重要的是要注意,如果嵌套五次,则setTimeout至少要经受四毫秒的强制延迟。[请参阅html规范](https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers) (2认同)

Ama*_*pta 16

关于事件循环如何工作的一篇很棒的文章,并清除了一些误解. http://voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout/

引用文章:

setImmediate在I/O队列回调完成或超时后调用回调.setImmediate回调放在Check Queue中,在I/O队列之后处理.

setTimeout(fn, 0)回调放在Timer Queue中,并在I/O回调和Check Queue回调后调用.作为事件循环,在每次迭代中首先处理计时器队列,因此首先执行哪一个取决于哪个阶段事件循环.

  • setTimeout 队列在 I/O 回调之前处理。参考:https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/ (2认同)

小智 6

setImmediate()用于在I/O事件回调之后以及setTimeout和setInterval之前安排立即执行回调.

setTimeout()用于在延迟毫秒后安排执行一次性回调.

这就是文件所说的.

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

setImmediate(function() {
  console.log('setImmediate')
})
Run Code Online (Sandbox Code Playgroud)

如果你运行上面的代码,结果将是这样的......即使当前的文档声明"在I/O事件回调之后以及在setTimeout和setInterval之前安排"立即"执行回调." ..

结果..

的setTimeout

setImmediate

如果将示例包装在另一个计时器中,它总是打印setImmediate,后跟setTimeout.

setTimeout(function() {
  setTimeout(function() {
    console.log('setTimeout')
  }, 0);
  setImmediate(function() {
    console.log('setImmediate')
  });
}, 10);
Run Code Online (Sandbox Code Playgroud)

  • 你没有解释为什么你的表现发生了.这个答案对我没用. (15认同)
  • @Savannah在第一个结果中,请解释为什么在setImmediate之前首先执行setTimeout (3认同)
  • @AgusSyahputra检查出来:https://github.com/nodejs/node-v0.x-archive/issues/25788 (2认同)