【七】Node.js事件循环中的关闭队列


欢迎来到我们关于可视化 Node.js 事件循环的系列文章的第七篇,也是最后一篇。在上一篇文章中,我们探讨了队列检查及其在执行异步代码时的优先顺序。在本文中,我们将看一下事件循环中的最后一个队列,即关闭队列。

将回调函数加入队列

在我们研究本系列中的最后一个实验之前,我想指出关闭队列包含与异步任务的关闭事件相关联的回调函数。以下是将回调函数添加到关闭队列的示例:

1
2
3
readableStream.on("close", () => {
console.log("这是来自可读流关闭事件回调的消息");
});

所有先前处理其他队列的实验都已在以前的文章中进行了介绍。它们使用了 CommonJS 模块格式进行运行。

实验14

1
2
3
4
5
6
7
8
9
10
11
12
13
// index.js
const fs = require("fs");

const readableStream = fs.createReadStream(__filename);
readableStream.close();

readableStream.on("close", () => {
console.log("这是来自可读流关闭事件回调的消息");
});
setImmediate(() => console.log("这是 setImmediate 1"));
setTimeout(() => console.log("这是 setTimeout 1"), 0);
Promise.resolve().then(() => console.log("这是 Promise.resolve 1"));
process.nextTick(() => console.log("这是 process.nextTick 1"));

首先,我们导入 fs 模块。然后,我们使用 fs.createReadStream() 创建一个可读流。之后,我们使用 close() 方法关闭流。我们监听关闭事件,并添加一个监听器来记录“这是来自可读流关闭事件回调的消息”。

接着,我们有一些熟悉的方法:setImmediate()setTimeout()Promise.resolve().then() process.nextTick()

在调用堆栈执行所有语句后,除了 I/O 队列之外,每个队列中都会有一个回调。当没有更多的代码需要执行时,控制流进入事件循环。

首先,nextTick 队列中的回调被出列并执行。然后,执行 promise 队列中的回调,随后是 timer 队列中的回调。

接下来,事件循环转移到 check 队列,并出列并执行其回调。最后,控制流移动到close队列,在那里最后一个回调被出列并执行。

在事件循环的给定迭代中,close 队列回调在所有其他队列回调之后执行。

结论

事件循环是一个在 Node.js 中协调同步和异步代码执行的 C 程序。它管理六个不同的队列:nextTickpromisetimerI/Ocheck close

要将任务添加到 nextTick 队列中,我们使用 process.nextTick() 方法。要将任务添加到 promise 队列中,我们resolve or reject一个 promise。要将任务添加到 timer 队列中,我们使用 setTimeout() setInterval()

要将任务添加到I/O队列中,我们执行一个异步方法。要将任务添加到check 队列中,我们使用setImmediate() 函数。最后,要将任务添加到 close` 队列中,我们附加关闭事件监听器。

执行顺序遵循此处列出的相同顺序。但是,重要的是要注意,nextTickpromise 队列在每个队列之间以及在timercheck 队列中每个回调执行之间都会执行。