JS中的事件循环机制(Event Loop)

前言

众所周知,JavaScript是一门单线程语言,虽然在html5中提出了web-worker,但这并未改变JavaScript是单线程这一核心。

为了协调事件、用户交互、脚本、UI渲染和网络处理等行为,用户引擎必须使用 Event Loops。Event Loop包含两大类:一类是基于Browsing content,一种是基于Worker,二者是独立运行的。

任务队列

所有的任务可以分为同步任务和异步任务,同步任务,顾名思义,就是立即执行的任务,同步任务一般直接进入到主线程中执行。二异步任务,比如ajax请求,setTimeout定时器函数等都属于异步任务,异步任务会通过任务队列(Event Queue)的机制来进行协调


同步任务和异步任务分别进入到不同的执行环境,同步进入主线程,即主执行栈,异步进入 Event Queue。主线程内的任务执行完毕为空,回去 Event Queue 读取对应的任务,推入主栈中执行。

上述过程的不断重复就是我们说的Event Loop(事件循环)。
在事件循环中,每进行一次循环操作称为tick,每一次tick的任务处理模型是比较复杂的,其关键的步骤可以总结如下:

  1. 在此次tick中选择最先进入队列的任务(oldest task),如果有则执行(一次)
  2. 检查是否存在Microtasks,如果存在则不停地执行,直至清空Microtask Queue
  3. 更新render
  4. 主线程重复执行上述步骤

可以用一张图来说明下流程:



这里相信有人会想问,什么是microtasks?规范中规定,task分为两大类, 分别是Macro Task (宏任务)和Micro Task(微任务), 并且每个宏任务结束后, 都要清空所有的微任务,这里的Macro Task也是我们常说的task,有些文章并没有对其做区分,后面文章中所提及的task皆看做宏任务(macro task)。

(macro)task主要包含:script(整体代码)、setTimeout、setInterval、I/O、UI交互事件、setImmediate(Node.js 环境)

microtask主要包含:Promise、MutaionObserver、process.nextTick(Node.js 环境)

setTimeout/Promise等API便是任务源,而进入任务队列的是由他们指定的具体执行任务。来自不同任务源的任务会进入到不同的任务队列。其中setTimeout与setInterval是同源的。

参考

  • 你不得不知的Event Loop
  • 一次弄懂Event Loop(彻底解决此类面试问题)

你可能感兴趣的:(JS中的事件循环机制(Event Loop))