Node.js 0.10版本今天发布,并引入了setimmediation。API更改文档建议在进行递归nextTick调用时使用它。

根据MDN的说法,它似乎与process.nextTick非常相似。

什么时候应该使用nextTick,什么时候应该使用setimmediation ?


当前回答

简单来说,process.NextTick()将在事件循环的下一个tick执行。但是,setimmediation基本上有一个单独的阶段,该阶段确保在setimmediation()下注册的回调只会在IO回调和轮询阶段之后被调用。

请参考这个链接了解详细解释: https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c

其他回答

如果您希望将函数置于已经在事件队列中的任何I/O事件回调之后,请使用setimmediation。使用过程。nextTick可以有效地将函数排在事件队列的头部,以便在当前函数完成后立即执行。

因此,在试图使用递归分解长时间运行的cpu绑定作业的情况下,您现在会希望使用setimmediation而不是process。nextTick将在下一个迭代中排队,否则任何I/O事件回调都没有机会在迭代之间运行。

我建议你检查文档部分专门为循环得到更好的理解。摘录如下:

就用户而言,我们有两个类似的调用,但它们的名称令人困惑。

process.nextTick()在同一阶段立即触发 类的后续迭代或“tick”时触发setimmediation () 事件循环

本质上,名字应该互换。process.nextTick()比setimmediation()更立即触发,但这是过去的产物,不太可能改变。

这里有一些很好的答案,详细介绍了它们是如何工作的。

只需添加一个回答特定问题的答案:

什么时候应该使用nextTick,什么时候应该使用setimmediation ?


总是使用setimmediation。


Node.js事件循环、定时器和process.nextTick()文档包括以下内容:

我们建议开发人员在所有情况下都使用setimmediation(),因为它更容易推理(并且它导致代码与更广泛的环境兼容,如浏览器JS)。


在文档的前面,它会警告这个过程。nextTick可以导致……

一些糟糕的情况,因为它允许您通过递归process.nextTick()调用“饿死”您的I/O,这可以防止事件循环到达轮询阶段。

事实证明,处理。nextTick甚至可以让你挨饿

Promise.resolve().then(() => { console.log('this happens LAST'); });

process.nextTick(() => {
  console.log('all of these...');
  process.nextTick(() => {
    console.log('...happen before...');
    process.nextTick(() => {
      console.log('...the Promise ever...');
      process.nextTick(() => {
        console.log('...has a chance to resolve');
      })
    })
  })
})

另一方面,setimmediation“更容易推理”,并避免了这些类型的问题:

Promise.resolve().then(() => { console.log('this happens FIRST'); });

setImmediate(() => {
  console.log('this happens LAST');
})

因此,除非有特定的需要,流程的独特行为。nextTick,建议的方法是“在所有情况下使用setimmediation()”。

在回答的评论中,它没有明确地说明nextTick从Macrosemantics转移到Microsemantics。

在节点0.9之前(引入setimmediation时),nextTick在下一个调用堆栈的开始操作。

从节点0.9开始,nextTick操作在现有调用堆栈的末尾,而setimmediation操作在下一个调用堆栈的开始

查看https://github.com/YuzuJS/setImmediate获取工具和详细信息

你永远不应该使用process中断cpu负荷大的操作。

你不应该使用process.nextTick()中断这样的工作。这样做将导致一个永远不会清空的微任务队列——您的应用程序将永远被困在同一个阶段! ——托马斯·亨特使用Node.js的分布式系统

事件循环的每个阶段包含几个回调:

一旦process.nextTick()被触发,它将始终保持在相同的阶段。

例子

const nt_recursive = () => process.nextTick(nt_recursive);
nt_recursive(); // setInterval will never run

const si_recursive = () => setImmediate(si_recursive);
si_recursive(); // setInterval will run

setInterval(() => console.log('hi'), 10);

在本例中,setInterval()表示应用程序执行的一些异步工作,例如响应传入的HTTP请求。

一旦nt_recursive()函数运行,应用程序就会得到一个永远不会清空的微任务队列,异步工作也永远不会得到处理。

但是替代版本si_recursive()没有同样的副作用。

在检查阶段中调用setimmediation()会将回调添加到下一个事件循环迭代的检查阶段队列,而不是当前阶段的队列。

Case可能使用process.nextTick

使函数处理都异步进行。

function foo(count, callback) {
  if (count <= 0) {
    return process.nextTick(() => callback(new TypeError('count > 0')));
  }
  myAsyncOperation(count, callback);
}

——托马斯·亨特使用Node.js的分布式系统

在这种情况下,使用setimmediation()或process.nextTick()都可以;只是要确保你不会意外地引入递归。