JS中的事件循环(Event loop)

JavaScript 是一门单线程语言,为了使主线程不阻塞,Event Loop 就应运而生了。Event LoopJavaScript 的执行机制。

image

  • 同步和异步任务分别进入不同的执行“场所”,同步的进入主线程,异步的进入Event Table并注册函数。
  • 当指定的事情完成时,Event Table会将这个函数移入Event Queue。
  • 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
  • 上述过程会不断重复,也就是常说的Event Loop(事件循环)。

setTimeout

setTimeout 这个函数,是经过指定时间后,把要执行的任务加入到Event Queue中,又因为单线程任务要一个一个执行,如果前面的任务需要的时间大于 setTimeout 设定的时间,会导致执行任务的延迟大于设定的时间。

setInterval

setIntervalsetTimeout 差不多,只不过它是循环执行。对于执行顺序来说,setInterval 会每隔指定时间将注册的函数置入Event Queue,如果前面的任务耗时太久,那么同样需要等待。

Promise 与 process.nextTick(callback)

process.nextTick(callback) 类似node版的 setTimeout,在事件循环的下一次循环中调用 callback 回调函数。

Event Loop

除了广义的同步任务和异步任务,我们对任务有更精细的定义:

  • 宏任务(macro-task):整体代码script、setTimeout、setInterval、setImmediate、IO、UI交互事件
  • 微任务(micro-task):Promise、process.nextTick、MutaionObserver

不同的任务会进入相应的Event Queue,比如 setTimeoutsetInterval 会进入相同的Event Queue。

事件循环的顺序,决定js代码执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再次执行所有的微任务。

事件循环,宏任务,微任务的关系如图所示:
Event Loop

参考:
这一次,彻底弄懂 JavaScript 执行机制
Tasks, microtasks, queues and schedules