根据Node.js 文档,当事件循环进入其轮询阶段且轮询队列不为空时,轮询队列中的回调应在事件循环进一步进入其检查阶段之前执行。
然而,实际上,相反的情况会发生,即如果在事件循环进入轮询阶段时轮询和检查 (setImmediate) 队列都不是空的,则检查 (setImmediate) 队列中的回调总是在之前执行来自轮询队列的回调。
这是为什么?我在Node.js 文档中缺少什么?
这里遵循示例代码和来自Node.js 文档的引用。
来自Node.js 文档的引用:
轮询阶段有两个主要功能: 1.计算它应该阻塞和轮询I/O的时间,然后 2.处理轮询队列中的事件。 当事件循环进入轮询阶段并且没有安排定时器时, 将发生以下两种情况之一:
(a) - 如果轮询队列不为空,事件循环将迭代 通过其同步执行它们的回调队列 直到队列已用完, 或达到系统相关的硬限制。
(b) - 如果轮询队列为空,将会发生另外两种情况之一: - 如果脚本已由 setImmediate() 安排, 事件循环将结束轮询阶段并继续检查阶段 执行那些预定的脚本。 - 如果脚本没有被 setImmediate() 调度, 事件循环将等待回调被添加到队列中, 然后立即执行它们。 一旦轮询队列为空,事件循环将检查计时器 已达到时间阈值。如果一个或多个计时器准备就绪, 事件循环将回到计时器阶段 执行这些计时器的回调。
示例代码:
const fs = require(`fs`);
console.log(`START`);
const readFileCallback = () => {
console.log(`readFileCallback`);
};
fs.readFile(__filename, readFileCallback);
const setImmediateCallback = () => {
console.log(`setImmediateCallback`);
};
setImmediate(setImmediateCallback);
// Now follows the loop long enough to give the fs.readFile enough time
// to finish its job and to place its callback (the readFileCallback)
// into the event-loop's poll phase queue before the "main" synchronous part
// of the this code finishes.
for (let i = 1; i <= 10000000000; i++) {}
console.log(`END`);
// So when the event-loop starts its first tick there should be two callbacks
// waiting:
// (1) the readFileCallback (in the poll queue)
// (2) the setImmediateCallback (in the check queue)
// Now according to the Node.js DOCs, of these two waiting callbacks
// the readFileCallback should execute first, but the opposite
// is actually happening, that is setImmediateCallback executes first.