繁体   English   中英

了解 Node.js 中的事件循环和分区

[英]Understanding the event loop and partitioning in Node.js

我读过这个很好的文档指南: https://nodejs.org/en/docs/guides/dont-block-the-event-loop/

在那篇文章的某些部分,有人说是在不阻塞事件循环的情况下进行复杂计算:

假设您想在不阻塞事件循环的情况下在 JavaScript 中进行复杂的计算。 您有两个选择:分区或卸载。 您可以对计算进行分区,以便每个计算都在事件循环上运行,但定期产生(轮流)其他未决事件。

他们以这个代码示例为例来计算 0 + 1 + 2 +... + n 的平均值:

function asyncAvg(n, avgCB) {
  // Save ongoing sum in JS closure.
  var sum = 0;
  function help(i, cb) {
    sum += i;
    if (i == n) {
      cb(sum);
      return;
    }

    // "Asynchronous recursion".
    // Schedule next operation asynchronously.
    setImmediate(help.bind(null, i+1, cb));
  }

  // Start the helper, with CB to call avgCB.
  help(1, function(sum){
      var avg = sum/n;
      avgCB(avg);
  });
}

asyncAvg(n, function(avg){
  console.log('avg of 1-n: ' + avg);
});

我的问题是:

  1. 根据此文档链接: https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick

setImmediate将被执行如果轮询阶段脚本已被setImmediate()调度,则事件循环将结束轮询阶段并继续到检查阶段以执行那些调度的脚本。

但是如果我们在递归步骤中:

function help(i, cb) {
    sum += i;
    if (i == n) {
      cb(sum);
      return;
    }

    // "Asynchronous recursion".
    // Schedule next operation asynchronously.
    setImmediate(help.bind(null, i+1, cb));
  }

那么 poll 应该是空的,但是setImmediate命令,因此它应该继续运行递归,那么它如何给其他代码同时执行的机会呢? 在事件循环调度方面。

  1. 为什么对于非常大的n没有RangeError: Maximum call stack size exceeded错误,但是如果我更改此行:
setImmediate(help.bind(null, i+1, cb));

到这一行:

help(i+1, cb);

然后错误RangeError: Maximum call stack size exceeded弹出。 我的意思是,使用setImmediate无论如何都应该保留由递归引起的函数堆栈,不是吗?

那么 poll 应该是空的,但是 setImmediate 命令,因此它应该继续运行递归,那么它如何给其他代码同时执行的机会呢?

因为setImmediate将回调安排在poll阶段完成后发生。 这些回调在check阶段运行。 check期间添加更多回调会安排它们,但不会导致它们运行; 下次循环进入poll阶段时会发生这种情况,看到有挂起的回调,然后进入check阶段。

为什么对于非常大的 n 没有 RangeError: Maximum call stack size exceeded 错误

因为递归不是立即的,所以它不会消耗堆栈空间。 setImmediate只是安排一个回调,它不调用回调。 您的代码结束,释放其堆栈资源,并且事件循环继续。 稍后,您通过setImmediate安排的回调将运行,短暂地使用少量堆栈空间。

相反,当您立即调用help时,这是分配一个新的堆栈帧,如果您使用大的n ,则分配的堆栈帧过多并用完堆栈。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM