关于Event Loop网上有很多文章都有讲解,包括我自己也有几篇文章有讲述event loop相关内容。之前写了一篇文章总结了Nodejs中event loop的原理,这里的event loop指的是服务端nodejs的event loop。此外,另一篇文章中有讲到前端浏览器中event loop的执行过程(4.Event Loop & Callback)。
显然,这里出现了两个event loop,那么这里说到的两个event loop是不是一回事,是不是相同的东西呢?
事实上,这两个是不完全相同的。一个归属于前端浏览器中,一个归属于nodejs后端服务中。但很多文章在讲event loop的时候并木有区分具体是说的哪个,大多数是以一个笼统的概念在解释event loop,所以很多细节仔细想想老是有不明白的地方。
今天在Quora上看到一篇相关的回答觉得说的挺清楚的。加上自己的理解和查阅相关资料,总结如下。
Event loop in Front-End
前端环境中实际上说的就是浏览器环境,那么首先得搞清楚浏览器中跟执行JS代码相关的有哪些东西。
- core JS engine(我们熟悉的V8引擎,即JS interpreter)
- web environment(如排版引擎,渲染引擎等)Browser更加详细内容请查看这里
1. core JS engine
JS引擎是实现了ECMAScript标准,在该标准中,并未提及event loop,说明标准中并不要求需要有event loop。
但像setTimeout()
,setInterval()
这些方法的回调函数是保存在任务队列中的,再由event loop轮询队列放到执行栈中执行,这在很多文章中都有提及。
这说明浏览器中的event loop并不是由JS引擎(如V8)提供,而是由浏览器的其他部件提供的。
关于setTimeout()
,setInterval()
这些Timer
相关的规范,其实并不属于ECMAScript标准,关于是否纳入该标准其实一直都在争论中,但到目前为止还没有纳入。
那么有人要问了,那我们写JS代码不是经常用这些方法吗?确实是,因为它们是在W3C标准中定义了,它是属于browser environment中的window对象的方法(window.setTimeout
)。这就是后面要将的Web Environment。
2. Web Environment
这里web environment包含了DOM API,XMLHttpRequest,setTimeout()
等 Web标准中规范的东西。Front-End中提到的event loop也是由web environment提供的,具体的可以参考W3C中的规范。这里说到:
There is also at most one event loop per unit of related similar-origin browsing contexts (though several units of related similar-origin browsing contexts can have a shared event loop).
从中可以知道每个browsing context中至多有一个event loop。
再回顾下浏览器中event loop的这张图:
结合上述所讲,再看这张图就清晰很多了,左边代表JS引擎(core JS engine),这里的event loop是所属在web environment中,轮询调用任务队列中的js代码扔给JS引擎中执行。我们代码中的setTimeout()
,ajax
请求,DOM操作等是调用web environment中的Web API进行调用。
Event Loop in NodeJS
在NodeJs中,event loop也是只有一个,也即是主线程,是一直运行的。与分析浏览器一样,这里也先搞清楚NodeJS中都有些什么东西。这里直接给出一张图:
可以看到,与浏览器一样,Nodejs中也同样采用了JS引擎(这里是V8)作为JS的编译器,同时通过Libuv这个库提供了读取文件、网络资源请求等I/O操作。
NodeJS中的event loop也正是由Libuv提供的,关于nodejs中的event loop细节部分这里不再赘述,详细内容可以看Node.js design pattern : Reactor (Event Loop)这篇文章。
总结
- NodeJs的event loop由Libuv提供。
- 浏览器中的event loop由browsing context提供。
- 两者并不是一回事,不要混为一谈。