一文彻底弄懂 "Event Loop"
前言
什么是
Event Loop
事件循环机制?有什么作用?为什么面试经常问到???我在学习浏览器和NodeJS的Event Loop时翻阅了技术类型网站上大量的文章,这些文章写的都很不错、讲解的也很到位,那为什么我还是要写这篇文章呢?其实呢是由于这些文章都是针对特定的一些案例、一些情况来解释Event Loop
,当很多篇文章凑在一起综合来看,才可以对这些概念有较为深入的理解。
于是,我在看了大量文章之后,想要写这么一篇博客,不采用官方的描述,结合自己的理解以及示例代码,用最通俗的语言表达出来。希望大家可以通过这篇文章,了解到Event Loop到底是一种什么机制,浏览器和NodeJS的Event Loop又有什么区别。如果在文中出现书写错误的地方,欢迎大家留言一起探讨。(PS: 其实是很多篇文章组合在一起后才理解了这些。。。如果对你有用,就请给个Star吧~ 如有错误,欢迎指出~)
Event Loop
是什么?
Event Loop
是一个执行模型,在不同的地方有不同的实现。浏览器和NodeJS基于不同的技术实现了各自的Event Loop
。
- 浏览器的
Event Loop
是在html5的规范中明确定义。 - NodeJS的
Event Loop
是基于libuv实现的。可以参考Node的官方文档以及libuv的官方文档。 - 为了解决JS
多线程
高效运行,衍生出了主线程和任务队列(同步任务和异步任务),主线程一直在循环运行任务,当执到异步任务的时候,不等待它执行完,而是把异步任务放入到队列中,当所有的同步任务都执行完毕之后,任务队列就会通知主线程执行队列中的任务。之后再重复之前的步骤,就变成了一个循环,也就是我们说的Event Loop
事件循环机制。
浏览器线程
我们常说 JS 是单线程语言,但是别忘了常见的浏览器内核可都是多线程的,多个线程间会进行不断通讯,通常会有如下几个线程:
- GUI 渲染进程
- JS 引擎线程
- 定时器线程
- 事件触发线程
- 异步 HTTP 请求线程
- 请认真阅读以下代码,并尝试输出?
1 | setTimeout(function () { |
Microtask 与 Macrotask(宏队列和微队列)
在大多数解释 JS Event Loop 的文章中,鲜有谈及 Miscrotask 和 Macrotask 这两个概念,但这两个概念却是非常的重要,我在翻阅 Zone.js Primer 时,里面就经常会提及这两个概念,当时也是看的云里雾里的,这也是我写这篇文章的原因之一。
Macrotask(宏队列),也叫tasks。 一些异步任务的回调会依次进入macro task queue(宏任务队列),等待后续被调用,这些异步任务包括:
- setTimeout
- setInterval
- setImmediate (Node独有)
- requestAnimationFrame (浏览器独有)
- I/O
- UI rendering (浏览器独有)
Microtask(微队列),也叫jobs。 另一些异步任务的回调会依次进入micro task queue(微任务队列),等待后续被调用,这些异步任务包括:
process.nextTick (Node独有)
Promise
Object.observe
MutationObserver
(注:这里只针对浏览器和NodeJS)
setTimeout(fn,0),会执行一个异步操作,会放到异步队列中,并在同步任务执行完毕后,尽早执行!
未完待续
参考资料
彻底理解 JS Event Loop(浏览器环境)
JavaScript 运行机制详解:再谈Event Loop
并发模型与事件循环–MDN
浏览器与Node的事件循环(Event Loop)有何区别?
Tasks, microtasks, queues and schedules
HTLM5 EVENT LOOP DEFINITIONS
Node.js 事件循环