在阅读了很多关于NodeJS事件循环的内容之后,我仍然有一个疑问。
在我们的代码中,如果NodeJS运行时发现任何异步调用,它会将其推送到在后台线程上运行的任务/消息队列,并且V8继续在主线程上执行我们的进一步代码。完成该异步任务后,节点会将调用堆栈检查为空。如果调用堆栈为空,则只有节点在主线程上进行回调以进行处理。否则它必须等到调用堆栈为空。
到目前为止,我认为,我是对的。
怀疑:如果异步任务完成且调用堆栈不为空,则回调将需要等待调用堆栈变空。现在假设,如果我的调用堆栈中有如此多的调用可能需要很多次(少于异步任务完成)并且异步任务已经完成,那么就不必再等待调用堆栈变空。 / p>
Node是否以这种方式设计,只有回调需要等待调用堆栈变空?
答案 0 :(得分:1)
如果异步任务完成且调用堆栈不为空,则回调将需要等待调用堆栈变空。现在假设,如果我的调用堆栈中有如此多的调用可能需要很多次(少于异步任务完成)并且异步任务已经完成,那么就不必再等待调用堆栈变空。 / p>
那是对的。例如,如果您调用fs.readFile()
然后运行长时间运行的for
循环,那么如果读取文件操作在for
循环结束之前完成,它仍然必须等待{{ 1}}循环。
例如,请考虑以下代码:
for
let fs = require('fs');
fs.readFile(__filename, 'utf-8', (err, data) => {
if (err) {
console.log('Error:', err.message);
} else {
console.log(data);
}
});
for (let i = 0; i < 1e9; i++);
回调必须等待readFile
循环完成。
Node是否以这种方式设计,只有回调需要等待调用堆栈变空?
是。您需要确保通过长时间运行的计算阻止主线程阻止调用堆栈变空来阻止事件循环。这不仅是Node,这也是所有客户端JavaScript的工作原理。
有关详细信息,请参阅此答案: