javascript - setTimeout 阻止事件循环

标签 javascript node.js settimeout

我正在阅读一篇文章,其中指出要创建非阻塞/异步函数,setTimeout 的使用至关重要。我认为传递给 setTimeout 的函数在后台运行。然后我在另一篇文章中读到 setTimeout 在函数被触发时确实会阻止事件循环。因此,我尝试了以下功能来测试。

function getit(cb) {
var i = 0;
 setTimeout(function() {
  while (i < 200000) { i++; console.log(i); }
  cb(i); 
 } , 1000); 
 console.log(i); 
}

getit(function(message) { console.log(message); });

显然,当 1000 毫秒过去并且该执行该函数时,线程被阻塞并且我的浏览器卡住。我的问题是,如果异步代码不应该阻塞线程,那么当函数在时间流逝时执行而不是在后台执行时,这怎么可能?看起来这只是一个延迟,但最终该函数将逐行执行并无论如何都会阻塞循环。有什么我遗漏或困惑的吗?

最佳答案

Node.js执行模型可以用以下代码表示:

function main() {
   while(running) {
     var timerCb = getNextTimedoutCallback();
     if( timerCb ) timerCb(); // execute it

     var ioCb = getNextCompleteIOOperationCallback();
     if( ioCb ) ioCb(); // execute it
   }
}

一切都在单线程中运行。 IO 操作在工作线程中运行,并填充已完成 IO 操作的内部队列。 getNextCompleteIOOperationCallback(); 只是从队列中提取已完成的操作。

以同样的方式setTimeout()简单地将函数及其结束时间推送到计时器队列(按结束时间排序)。并且 getNextTimedoutCallback() 提取下一个过期超时(如果有)。

如您所见,计时器函数或 IO 回调都可以阻止整个过程。 这就是 cooperative multitasking .

关于javascript - setTimeout 阻止事件循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38176083/

相关文章:

javascript - 具有不同时间的for循环中的setTimeout

javascript - Google Charts 饼图始终显示 100%

javascript - 计时器触发的 angularJS 性能问题

javascript - 使用 Material-ui 的 TextField 和 getInputProps 在输入旁边创建标签

javascript - 尽管导入模块并包含 CUSTOM_ELEMENTS_SCHEMA 架构,但组件不是已知元素

javascript - 停止 AngularJS 中的 setTimeout 函数(提示 : use $timeout)

javascript - Flex-basis 不扩展宽度

javascript - 错误 : spawn ENOENT for png files when using grunt-contrib-imagemin

javascript - 在 node.js 中使用异步 waterfall

javascript - 如何在 for 循环中使用 setInterval 或 setTimeout?