ONFUNS 学习&生活随笔

JS运行机制 Event Loop概要

特点:js单线程通过事件循环(event loop)实现

Event Loop靠任务队列实现,任务分为宏任务、微任务

宏任务:
  • script代码
  • setTimeout/setInterval
  • setImmediate(nodejs环境中)
微任务:
  • promise.then/catch
  • process.nextTick(nodejs环境中)

执行顺序:

  • 执行一个宏任务,过程中如果遇到微任务,就将其放到微任务的【事件队列】里
  • 当前宏任务执行完成后,会查看微任务的【事件队列】,并将里面全部的微任务依次执行完,然后执行下个宏任务
  • 以上循环执行

demo解析:

console.log(1)
setTimeout(()=> console.log(2),0)
new Promise((resove,reject) => {
    console.log(3)
    setTimeout(()=> console.log(4),0)
    resove()
}).then(()=> console.log(5))
console.log(6)

结果依次输出1,3,6,5,2,4

执行顺序分析如下:

首先执行当前队列的所有宏任务:执行宏任务console.log(1),setTimeout为定时器放入下一次宏任务队列,new Promise内部函数为宏任务执行console.log(3),再次遇到setTimeout放入下一次宏任务队列,then为微任务放入当前微任务队列,执行console.log(6)。此时队列宏任务执行结果为1,3,6。然后执行微任务console.log(5),执行完毕进入下一次事件循环执行宏任务setTimeout,根据队列先进先出并且满足秒数大小的情况下执行console.log(2),最后执行console.log(4)

简化一下上面的步骤,可以用下面的伪代码描述EL循环过程:

一个宏任务,所有微任务(,更新渲染),一个宏任务,所有微任务(,更新渲染)......

注意点:微任务为当前宏任务队列的尾端执行,setTimeout异步任务在主线程空闲时下一个宏任务队列的始端执行

流程图

Nodejs环境中的Event Loop由libuv库实现与浏览器端不同,具体可参考官方文档event-loop-timers-and-nexttick