我是node.js的新手,对理解事件循环有点困惑。据我所知https://github.com/nodejs/node/blob/master/doc/topics/event-loop-timers-and-nexttick.md,事件循环阶段只处理setTimeout,setInterval,setImmediate,process.nextTick,promises和一些I / O回调。
我的问题是,如果我有以下代码:
for(var i = 0; i< 100000000; i ++) ;
上述代码将在哪个阶段执行?
答案 0 :(得分:1)
常规JavaScript代码(如示例中的for
循环)在清除队列之前执行。节点要做的第一件事就是运行你的代码,并且只会在你的代码完成后调用回调,超时结果,I / O结果等。
例如,您可以尝试以下代码:
fs.open('filename', 'r', () => {
console.log('File opened.');
});
for (var i = 0; i < 100000000; i++);
console.log('Loop complete.');
无论您的循环变量有多大或多小,“循环完成”将始终出现在“文件打开”之前。这是因为只有一个线程,节点无法运行您提供给fs.open函数的回调,直到循环代码完成。
请记住,节点不再有“主”线程。大多数长时间运行的节点程序将很快运行main.js中的代码,后续代码将全部来自回调。初始执行的目的是定义这些回调的发生方式和时间。
答案 1 :(得分:0)
在节点事件循环doc(https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick)中,以下代码为例:
const fs = require('fs');
function someAsyncOperation(callback) {
// Assume this takes 95ms to complete
fs.readFile('/path/to/file', callback);
}
const timeoutScheduled = Date.now();
setTimeout(() => {
const delay = Date.now() - timeoutScheduled;
console.log(`${delay}ms have passed since I was scheduled`);
}, 100);
// do someAsyncOperation which takes 95 ms to complete
someAsyncOperation(() => {
const startCallback = Date.now();
// 10ms loop
while (Date.now() - startCallback < 10) {
// do nothing
}
});
循环根据阶段继续扫描,在fs.readFile()
完成后,轮询队列为空,因此将添加并立即执行其回调。在执行定时器之前,回调保持阻塞10ms循环。这就是延迟显示的原因:
105ms have passed since I was scheduled
而不是您期望的100毫秒。
您的大多数代码都会存在于回调中,因此将在投票阶段执行。如果没有,就像在你的例子中一样,它将在进入任何阶段之前执行,因为它将阻止事件循环。
警告是由setImmediate
安排的回调,它将进入检查阶段,然后在下一个循环中恢复轮询阶段。