tus*_*har 2 javascript event-loop node.js
我已阅读官方文档和许多其他博客,process.nextTick()但我对某些主题有点困惑。
首先,写入中的回调process.nextTick()在下一次迭代开始之前执行。
其次,当在 I/O 周期内时,事件循环当前处于轮询阶段。在轮询阶段之后,事件循环进入检查阶段,在该阶段执行setImmediate方法中调用的任何回调。
现在在下面的代码中
const fs = require('fs');
function main() {
fs.readFile('./xy.txt', function(err, buff){
setTimeout(()=> console.log("timeout inside fs"),0);
setImmediate(()=> console.log("immediate inside fs"));
process.nextTick(()=>{console.log("process.nextTick")});
console.log("inside fs");
})
console.log("called inside main fn in first-iteration");
}
main();
console.log("called in first-iteration);
Run Code Online (Sandbox Code Playgroud)
输出将是:
const fs = require('fs');
function main() {
fs.readFile('./xy.txt', function(err, buff){
setTimeout(()=> console.log("timeout inside fs"),0);
setImmediate(()=> console.log("immediate inside fs"));
process.nextTick(()=>{console.log("process.nextTick")});
console.log("inside fs");
})
console.log("called inside main fn in first-iteration");
}
main();
console.log("called in first-iteration);
Run Code Online (Sandbox Code Playgroud)
在此期间, fs fn 的回调将被注册,并且上面两行将被控制台,因为入口脚本将在没有事件循环的情况下运行。现在事件循环的第一次迭代将从计时器阶段开始,因为没有计时器,它将进入挂起阶段,然后进入轮询阶段,其中有一个回调(fs fn 回调),事件循环开始执行 fs 回调,现在setTimeout回调和setImmediate回调将被注册。之后,process.nextTick回调将被注册到 nextTickQueue 中,该回调将在下一次迭代或tick(第二次迭代)中执行。现在轮询阶段结束后,我们已经inside fs登录到第三行。
接下来,事件循环应该进入检查阶段,其中setImmediate存在回调,并且应该记录immediate inside fs以下事件循环应该进入下一个阶段并且第一次迭代应该结束。在开始第二次迭代之前,process.nextTick应该记录,然后timeout inside fs应该最后记录。
从而使最终输出为:
called inside main fn in first-iteration
called in first iteration
inside fs
immediate inside fs
process.nextTick
timeout inside fs
Run Code Online (Sandbox Code Playgroud)
但输出结果是:
called inside main fn in first-iteration
called in first iteration
inside fs
process.nextTick
immediate inside fs
timeout inside fs
Run Code Online (Sandbox Code Playgroud)
某处写道,微任务(process.nextTick)以最高优先级执行,因此事件循环将放弃所有执行并乍一看执行微任务。但既然如此,inside fs之前又何必安慰呢process.nextTick?
process.nextTick()基本上,我很困惑,事件循环的各个阶段是如何进行的?
节点开发人员最大的误解之一是 process.nextTick 在接下来的刻度(迭代)中运行代码
在回答你的问题之前,我先告诉你几件事:
process.nextTick()从技术上讲,它不是事件循环的一部分。相反,nextTickQueue 将会在当前操作完成后进行处理,而不管事件循环的当前阶段如何。Next tik 队列与其他四个主队列分开显示,因为它不是由 libuv 原生提供的,而是在 Node 中实现的
在事件循环的每个阶段(计时器队列、IO 事件队列、即时队列、关闭处理程序队列是四个主要阶段)之前,在进入该阶段之前,Node 会检查 nextTick 队列中是否有任何已排队的事件。如果队列不为空,Node 将立即开始处理队列,直到队列为空,然后再进入事件循环下一阶段。
自 Node v11 以来,Node v11 中引入了一些更改,显着更改了 nextTick、Promise 回调、setImmediate 和 setTimeout 回调的执行顺序。
nextTikcs 和 Promise 回调队列在每个计时器和立即回调之间进行处理,无论相应队列中是否已存在其他超时回调和立即回调。
在nodejs11之前和nodejs11及以上版本运行此https://repl.it/@sandeepp2016/processNextTick#index.js,您会看到执行顺序的差异。
nextTick除了何时调用以及如何在 Nodejs 中执行同步和异步代码之外,您几乎正确地理解了流程。
当事件循环进入轮询阶段时,它将执行fs.read排队到 io 事件队列的回调。由于队列中没有更多的 io 事件回调,事件循环将进入检查阶段,但在运行检查阶段的回调之前,它将执行所有nexttikcs并承诺任务队列。这就是为什么process.nexttick在您的案例中打印,然后 immediate inside fs在检查阶段之后它将返回到计时器阶段并打印timeout inside fs.
对于你的最后一个问题,当程序进入main函数时,前三个调用是异步的,前两个调用将排队到事件循环中。但console.log("inside fs")会立即放入调用堆栈并由 Nodejs 主线程执行。process.next也将异步执行(不是 libuv 事件循环的一部分),但在轮询阶段之后和检查阶段之前,如图所示。因此它将inside fs在之前打印process.nextTick。
请记住,事件循环仅处理异步代码,同步代码直接在主线程中执行,无需事件循环。
欲了解更多详细信息,请阅读此内容
https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
| 归档时间: |
|
| 查看次数: |
1347 次 |
| 最近记录: |