【问题标题】:Are there significant differences between the Chrome browser event loop versus the node event loop?Chrome 浏览器事件循环与节点事件循环之间是否存在显着差异?
【发布时间】:2014-09-09 17:49:20
【问题描述】:

Philip Roberts 出色地解释了浏览器事件循环here,在调用堆栈、事件循环、任务队列以及像 webapis 这样的“外部”线程之间提供了清晰的解释。我的问题是这些并行节点事件循环中的等效组件,它们被称为基本相同的东西。也就是说,当我使用 Node 的文件和 web i/o 库进行调用时,这些都是在堆栈之外发生的事情,其回调在任务队列中排队?

【问题讨论】:

  • 是的,核心思想是一样的。 node.js 使用 Chrome 的 JS 引擎。
  • @apsillers 同意。我只是想确定是否有任何重大的概念差异需要注意。
  • 一个浏览器可能有多个事件循环(对于JS,对于DOM等),但是概念是一样的,是的。
  • @dandavis node.js 确实使用了 Chrome 的 JS 引擎 V8,但事件循环不是 V8 的一部分。 Node 使用基于 C++ 库 libuv 的事件循环,而 Chrome 则基于 libevent。 Deno 使用基于 Rust 的 tokIO
  • @dandavis 我同意。但它们“基本相同”的原因并不是因为它们都使用 V8。它与 Firefox 或 Deno 一样“基本相同”。它们“基本相同”的原因是它们的事件循环实现相似

标签: javascript node.js dom-events


【解决方案1】:

...当我使用 Node 的文件和 web i/o 库进行调用时,这些是在堆栈之外发生的事情,其回调在任务队列中排队?

是的,绝对的;它们是异步的,就像 Ajax 和 setTimeout 是异步的一样。他们在调用堆栈之外执行一些操作,当他们完成该操作时,他们将一个事件添加到队列中以供事件循环处理。

Node 的 API 提供了一种异步无操作,setImmediate。对于那个函数,我上面提到的“一些操作”是“什么都不做”,之后立即将一个项目添加到事件队列的末尾。

有一个更强大的process.nextTick 可以在事件队列的front 中添加一个事件,有效地插入队列并使所有其他排队的事件等待。如果递归调用,这可能会导致其他事件的延迟时间延长(直到到达maxTickDepth)。

【讨论】:

  • FWIW:Node.js 和 Chrome 确实不使用相同的事件循环实现。 Chrome/Chromium 使用 libevent,而 node.js 使用 libuv。
  • @mscdex say whaaaaat -- 很高兴知道;我会尽快编辑。如果您手头有任何参考资料,我很乐意将它们放入(当然,我会自己查找,看看是否能找到自己的参考资料)。
  • Here 是 Chromium 的包含 libevent 的源代码树。 Here 是使用 libuv 作为主事件循环的节点。两者都使用 v8 以及随之而来的所有内容(尽管节点可能使用与 Chrome 不同的 v8 版本,因为 Chrome 会定期更新)。
  • 问题:setTimeout(callback, 0);和 setImmediate(callback) 一样吗?
  • @DwarDoh 它们相似,但行为方式不同。你可以阅读更多here
【解决方案2】:

两者完全不同。浏览器的事件循环不依赖于 I/O 操作。但是 Node js 事件循环依赖于 I/O 操作。这里Node js事件循环的主要目标是分离出主进程,尝试异步执行I/O操作和其他定时器API。

另一个区别是我们在浏览器中没有 setImmediate() 函数。 setTimeout() 和 setImmediate() 的区别在于 setTimeout() 回调函数将在给定的最小阈值(以毫秒为单位)之后执行。但是在 setImmediate() 中,一旦任何 I/O 操作完成,如果在 setImmediate() 中给出了特定的代码,它将首先执行。

因为正常

setTimeout(() => {
    //some process
}, 0);

和

setImmediate(() => {
    //some process
});

是相同的,我们无法预测哪个会先执行。但是在 nodejs 事件循环机制下的 Node js 角度,如果两者都存在于任何 I/O 操作的回调下,setImmediate() 将首先执行。所以,

let fs = require('fs');
fs.readFile('/file/path', () => {
   setTimeout(() => {
      console.log('1');
   }, 0);
   setImmediate(() => {
      console.log('2');
   });
});

上述代码的输出将是,

2
1

【讨论】:

    【解决方案3】:

    这是另一个视频link,由 Erin Zimmer 在 JS 会议上发表。她谈到了使用不同任务(如微任务和宏任务)以及其他环境(如 Node JS、浏览器和 Web 工作者)中的事件循环实现。

    首先观看 OP 提到的 Philip Roberts 的视频,然后观看此视频。

    【讨论】:

      猜你喜欢
      • 2011-07-22
      • 2010-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-23
      相关资源
      最近更新 更多