Chrome浏览器事件循环与节点事件循环之间是否存在显着差异?

Joh*_*alt 23 javascript node.js dom-events

菲利普·罗伯茨做了精彩的工作,解释的浏览器事件循环这里提供的调用堆栈,事件循环,任务队列,然后在"外"之类webapis线程之间的明确的解释.我的问题是这些与Node事件循环中的等效组件并行,并且它们被称为基本相同的东西.也就是说,当我使用Node的文件和Web i/o库进行调用时,这些是在堆栈外发生的事情,其回调在任务队列中排队?

aps*_*ers 15

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

是的,一点没错; 它们就像Ajax一样setTimeout异步并且是异步的.它们在调用堆栈之外执行某些操作,当它们完成该操作时,它们将事件添加到队列以由事件循环处理.

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

有一个更强大的功能process.nextTick,可以在事件队列的前面添加一个事件,有效地切入线并使所有其他排队事件等待.如果以递归方式调用,这可能会导致其他事件延迟(直到达到maxTickDepth).

  • FWIW:Node.js和Chrome不会**使用相同的事件循环实现.Chrome/Chromium使用libevent,而node.js使用libuv. (13认同)
  • [这里](https://chromium.googlesource.com/chromium/chromium/+/master/third_party/libevent/README.chromium)是Chromium的包含libevent的源代码树.[here](https://github.com/joyent/node/blob/962e651476ce2035ce6e15eff5abd0f9c54e039c/src/node.cc#L3629-L3640)是使用libuv作为主事件循环的节点.两者都使用v8及其附带的所有内容(尽管节点可能使用不同版本的v8而不是Chrome,因为Chrome会定期更新). (7认同)
  • @mscdex说whaaaaat - 很高兴知道; 我会尽快编辑.如果您手头有任何参考资料,我很乐意将它们放进去(当然,我会自己查阅,看看我是否可以找到我自己的一个). (2认同)
  • 问题:是setTimeout(回调,0); 和setImmediate(回调)一样? (2认同)

Pri*_*oss 8

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

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

因为正常情况下

setTimeout(() => {
    //some process
}, 0);
Run Code Online (Sandbox Code Playgroud)

setImmediate(() => {
    //some process
});
Run Code Online (Sandbox Code Playgroud)

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

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

上述代码的输出将是,

2
1
Run Code Online (Sandbox Code Playgroud)