JavaScript事件循环和Node.js事件循环有什么不同?

15
在JavaScript中,引擎使用事件循环。这里有一张图来说明它,来源于文章
(来源:mybalsamiq.com) 对于Node.js,事件循环也是在这里实现的。引用自问题

Node.js事件循环在单个线程下运行,这意味着您编写的应用程序代码在单个线程上评估。Nodejs本身通过libuv使用许多线程,但在编写nodejs代码时,您永远不必处理这些线程。

然而,对于 Node.js 的事件循环,我仍然感到抽象。

  • 有没有任何图片可以更清晰地介绍它?
  • 这两个事件循环有什么不同?
3个回答

17

Node.js的事件循环实现与基于浏览器的事件循环不同。

这是Node.js社区中一个很大的困惑点。

虽然Node.js使用Google V8作为其运行时,但它并没有使用V8来实现事件循环。

Node.js使用C编写的Libuv库来实现事件循环。

你所看到的上面的图表适用于JS事件循环,但对于Node.js事件循环来说则不同。

要完全理解Node.js事件循环,有三个参考资料需要学习:

  1. https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
  2. http://docs.libuv.org/en/v1.x/design.html
  3. https://www.youtube.com/watch?v=sGTRmPiXD4Y

2
如果你要争论这个问题,那么你也可以说Firefox有一个不同的事件循环,这是荒谬的。当然,不同的实现有不同的实现方式,但是事件循环——Firefox、V8、Edge、Internet Explorer、Adobe Flash(livescript——一种ECMAScript兼容语言)、Adobe Photoshop(javascript)、Node.js和Rhino(还有人记得这个服务器端引擎吗?)背后的响应式设计模式是相同的。 - slebetman
抱歉,但在这一点上你是错误的。你不必相信我,但如果你观看 Bert Belder 的这个视频,他是 Nodejs 事件循环库(Libuv)的共同作者之一,他谈到了这个确切的问题。https://www.youtube.com/watch?v=PNa9OMajw9wNodejs 使用与 ECMAScript 兼容的浏览器不同的事件循环模型。我提供的链接清楚地说明了这一点。 - Kane Hooper
2
我阅读了源代码。事件循环模型完全相同。唯一的区别是Node使用线程池来管理磁盘I/O - 但现在与浏览器的WebWorkers线程实现类似。网络I/O的结构和围绕它的事件循环是相同的。我自己多次编写了这样的事件循环。细节总是不同,但架构是相同的。 - slebetman
10
@slebertman,仅仅因为他们持有不同观点就嘲笑别人的观点是没有建设性的。此外,问题问的是什么并不重要,即使背后的架构使用了相同的模式。如果我在问“有什么不同之处”,我希望知道实现上的差异以及原因,感谢您阅读源代码并用其他形式实现它,但请避免笼统概括。同时请注意,这种混淆可能来自作者的表述,所以最好以不居高临下的方式与他交流。 - iwaduarte

13

Chrome和Node都有自己的事件循环(event-loop)。

浏览器或Node中的事件循环不是V8的一部分。事件循环是由浏览器或Node提供的不同应用程序/依赖库的一部分。

它们不使用V8的事件循环。

V8确实实现了一个事件循环,它在那里

但是它可以被覆盖或替换,这正是Chrome和NodeJS同时执行的操作。

浏览器(Chrome)

V8仅执行JavaScript代码(if语句,for语句,函数,算术运算等),然后将操作交给Libevent

除了JavaScript引擎V8(Chrome使用V8)之外,浏览器(例如Chrome)还包含不同的应用程序/依赖库,可以执行各种操作,如发送HTTP请求,监听DOM事件,使用setTimeout或setInterval延迟执行,缓存,数据库存储等等。

因此,浏览器(例如Chrome)使用依赖库Libevent来实现事件循环。


Node.js

V8只执行您的JavaScript(if和else语句,for语句,函数,算术运算等),然后将操作交给Libuv。默认情况下,JavaScript不支持网络和文件系统操作。Libuv与V8一起工作,以便V8运行JavaScript,而Libuv将处理I/O任务。

除了JavaScript引擎V8外,在Node.js中还包含不同的应用程序/依赖项/库,可以执行各种操作,例如网络,文件系统操作,监听系统事件,使用setTimeout,setInterval,setImmediate,process.nextTick延迟执行等等。

因此,Node.js使用依赖项Libuv来实现事件循环。


如果回调队列(阶段)中没有任务,Node的事件循环将处于空闲状态,但Chrome的事件循环会继续运行。

Chrome的事件循环就像旋转木马,而Node的事件循环则像过山车

还有其他差异,您可以在这里查看。


-7
这两个事件循环有什么区别?
没有。Node.js1 就是 JavaScript 引擎。
1:或者更准确地说,其中之一,还有其他实现相同语言和相同事件循环概念的引擎。
有没有任何形象的图片可以更清楚地介绍它?
有很多。但我认为动画更好:-) Philip Roberts 的 这个 jsconf 演讲 在各个方面都受到赞扬。

1
@iwaduarte 这个问题并没有询问libuv和libev之间的区别吧?你找到的要点可能在Nodejs事件循环(深入探讨)或者在POSIX系统上,libuv只是libev的包装器吗? - Bergi
@Nickon 请解释一下哪里有问题,这样我才能改善它。 - Bergi
@Nickon 请具体说明,不要只是放一个视频链接。或者您可以自己回答,这样就能清楚地看出您的观点有何不同了。 - Bergi
这个答案是多么的错误啊... 不,nodejs不是JS引擎,v8才是,node只是环境运行时。不,浏览器(HTML)的事件循环和node的事件循环根本不一样。它们的处理模型完全不同(HTMLnode)。 - Kaiido
@Kaiido 或许我被“在 JavaScript 中,事件循环是在引擎中使用的”这句话所迷惑了。而且 OP 从来没有提到浏览器事件循环,而始终只是指整个“JavaScript”。 - Bergi
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接