Node.js 0.10版本今天发布,并引入了setimmediation。API更改文档建议在进行递归nextTick调用时使用它。
根据MDN的说法,它似乎与process.nextTick非常相似。
什么时候应该使用nextTick,什么时候应该使用setimmediation ?
Node.js 0.10版本今天发布,并引入了setimmediation。API更改文档建议在进行递归nextTick调用时使用它。
根据MDN的说法,它似乎与process.nextTick非常相似。
什么时候应该使用nextTick,什么时候应该使用setimmediation ?
当前回答
举个例子:
import fs from 'fs';
import http from 'http';
const options = {
host: 'www.stackoverflow.com',
port: 80,
path: '/index.html'
};
describe('deferredExecution', () => {
it('deferredExecution', (done) => {
console.log('Start');
setTimeout(() => console.log('setTimeout 1'), 0);
setImmediate(() => console.log('setImmediate 1'));
process.nextTick(() => console.log('nextTick 1'));
setImmediate(() => console.log('setImmediate 2'));
process.nextTick(() => console.log('nextTick 2'));
http.get(options, () => console.log('network IO'));
fs.readdir(process.cwd(), () => console.log('file system IO 1'));
setImmediate(() => console.log('setImmediate 3'));
process.nextTick(() => console.log('nextTick 3'));
setImmediate(() => console.log('setImmediate 4'));
fs.readdir(process.cwd(), () => console.log('file system IO 2'));
console.log('End');
setTimeout(done, 1500);
});
});
将给出以下输出
Start // synchronous
End // synchronous
nextTick 1 // microtask
nextTick 2 // microtask
nextTick 3 // microtask
setTimeout 1 // macrotask
file system IO 1 // macrotask
file system IO 2 // macrotask
setImmediate 1 // macrotask
setImmediate 2 // macrotask
setImmediate 3 // macrotask
setImmediate 4 // macrotask
network IO // macrotask
我希望这能帮助你理解其中的区别。
更新:
使用process.nextTick()延迟的回调在任何其他I/O之前运行 事件被触发,而使用setimmediation(),执行被排队 在已经在队列中的任何I/O事件后面。 Node.js设计模式,作者Mario Casciaro(可能是关于Node.js /js最好的书)
其他回答
如果您希望将函数置于已经在事件队列中的任何I/O事件回调之后,请使用setimmediation。使用过程。nextTick可以有效地将函数排在事件队列的头部,以便在当前函数完成后立即执行。
因此,在试图使用递归分解长时间运行的cpu绑定作业的情况下,您现在会希望使用setimmediation而不是process。nextTick将在下一个迭代中排队,否则任何I/O事件回调都没有机会在迭代之间运行。
在回答的评论中,它没有明确地说明nextTick从Macrosemantics转移到Microsemantics。
在节点0.9之前(引入setimmediation时),nextTick在下一个调用堆栈的开始操作。
从节点0.9开始,nextTick操作在现有调用堆栈的末尾,而setimmediation操作在下一个调用堆栈的开始
查看https://github.com/YuzuJS/setImmediate获取工具和详细信息
举个例子:
import fs from 'fs';
import http from 'http';
const options = {
host: 'www.stackoverflow.com',
port: 80,
path: '/index.html'
};
describe('deferredExecution', () => {
it('deferredExecution', (done) => {
console.log('Start');
setTimeout(() => console.log('setTimeout 1'), 0);
setImmediate(() => console.log('setImmediate 1'));
process.nextTick(() => console.log('nextTick 1'));
setImmediate(() => console.log('setImmediate 2'));
process.nextTick(() => console.log('nextTick 2'));
http.get(options, () => console.log('network IO'));
fs.readdir(process.cwd(), () => console.log('file system IO 1'));
setImmediate(() => console.log('setImmediate 3'));
process.nextTick(() => console.log('nextTick 3'));
setImmediate(() => console.log('setImmediate 4'));
fs.readdir(process.cwd(), () => console.log('file system IO 2'));
console.log('End');
setTimeout(done, 1500);
});
});
将给出以下输出
Start // synchronous
End // synchronous
nextTick 1 // microtask
nextTick 2 // microtask
nextTick 3 // microtask
setTimeout 1 // macrotask
file system IO 1 // macrotask
file system IO 2 // macrotask
setImmediate 1 // macrotask
setImmediate 2 // macrotask
setImmediate 3 // macrotask
setImmediate 4 // macrotask
network IO // macrotask
我希望这能帮助你理解其中的区别。
更新:
使用process.nextTick()延迟的回调在任何其他I/O之前运行 事件被触发,而使用setimmediation(),执行被排队 在已经在队列中的任何I/O事件后面。 Node.js设计模式,作者Mario Casciaro(可能是关于Node.js /js最好的书)
这里有一些很好的答案,详细介绍了它们是如何工作的。
只需添加一个回答特定问题的答案:
什么时候应该使用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()”。
我建议你检查文档部分专门为循环得到更好的理解。摘录如下:
就用户而言,我们有两个类似的调用,但它们的名称令人困惑。
process.nextTick()在同一阶段立即触发 类的后续迭代或“tick”时触发setimmediation () 事件循环
本质上,名字应该互换。process.nextTick()比setimmediation()更立即触发,但这是过去的产物,不太可能改变。