什么是事件循环
事件循环是 Javascript 引擎实现异步操作的一种机制。
Javascript 引擎都是单线程的,任何时刻最多只能处理一个任务,所以这里的异步,只是宏观层面的“同时进行”,类似于操作系统层面的“并发”概念。
三个概念
主线程
Javascript 引擎是用来实现 ECMAScript 标准的,Node 中是 V8,Chrome 中也是 V8,Safari 中是JavaScript Core,Firefox 中是 SpiderMonkey。所有的引擎都是单线程的,这个单线程就是所谓的主线程,所有的任务都在主线程上执行。
异步处理模块
引擎提供了多种异步处理模块,如定时器、网络请求、Promise、I/O、UI rendering 等。在代码中调用这些异步方法,相当于对这部分代码做了“异步”标记。引擎在解释运行这些代码时,会进行特殊处理,最终在主线程中执行。
任务队列
任务队列存放了异步任务的回调处理,按照先进先出的方式顺序执行。任务队列分为两类:宏任务队列和微任务队列。
- 宏任务 macro tasks:
scriptsetTimeoutsetIntervalsetImmediateI/OUI rendering - 微任务 micro tasks:
process.nextTickPromiseObject.observerMutationObserver
事件循环的具体过程
引擎在解释运行一段代码时,同步任务被压入主线程执行,异步任务交由异步处理模块处理。当异步任务达到触发条件(比如计时器到时、网络请求返回),回调处理压入任务队列。当主线程同步任务全部执行结束后,从任务队列中取出回调函数执行。主线程不断检查是否有任务执行,没有的话就从任务队列中读取。
在浏览器环境中,主线程上执行任务的顺序是这样的:
- 执行同步任务直至线程清空
- 取出微任务队列中的任务执行直至清空
- 取出宏任务队列中一个任务执行
重复第二步和第三步。