2

前提梳理

  1. eventloop机制是C++写的,不属于JS。JS是个单线程的语言,来了任务就执行。
  2. eventloop机制在nodejs和chrome浏览器中是不同的。下面我们梳理chrome中的eventloop

Chrome的eventloop

宏任务和微任务

  1. 宏任务:一会儿就做的异步任务

    • setTimeout、setInterval
    • script(整体代码)
    • 渲染事件(解析DOM,计算布局,绘制)
    • 网络请求完成事件
  2. 微任务:优先级更高的异步任务

    • Promise.then
    • Promise.catch
    • MutationObserver

IO线程

渲染进程中的IO线程专门用来接收其他进程传进来的消息。如:

  1. 网络进程的HTTP响应消息
  2. 浏览器主进程的鼠标点击消息

定时触发器线程

渲染进程中的定时触发器线程专门用来处理setTimeout和setinterval任务。当对应的时间到了之后将回调函数作为宏任务加入渲染进程的任务队列中。

XMLHttpRequest

  • 调用xhr.send()后渲染进程将请求发送给网络进程。
  • 网络进程接收到HTTP响应信息后以IPC的方式通过IO线程向渲染进程提交消息,渲染进程将xhr的回调函数作为宏任务加入任务队列。
  • 执行到该任务时根据对应的状态执行不同的回调函数(onerror,onreadystatechange)

运行机制

执行顺序

  1. script标签内的代码作为宏任务。向调用栈中压入全局上下文开始执行。
  2. 执行过程:遇到宏任务,加入宏任务任务队列中;遇到微任务,加入在当前宏任务的微任务度列中。每个宏任务会创建自己的微任务队列。
  3. JS同步代码执行完之后,宏任务即将结束之前,将该宏任务对应的微任务队列的任务全部取出依次执行。若执行过程中又遇到微任务则加入当前微任务队列队尾。
  4. 微任务队列清空后本轮eventloop结束。从任务队列取出一个宏任务,将宏任务中的代码取出,初始化全局上下文开始执行。回到2.

实例

setTimeout(() => console.log(4)) 
new Promise(resolve => {  
   resolve() 
   console.log(1) 
}).then(() => { 
   console.log(3) 
}) 
console.log(2)

输出: 1 2 3(微任务) 4(宏任务)

进阶题目

async function fn1(){
    console.log(1)
    await fn2()
    console.log(2)
}
async function fn2(){
    console.log(3)
}
fn1()

new Promise(function(resolve){
    console.log(4)
    resolve()
}).then(()=>{
    console.log(5)}
)

输出:1 3 4 2 5

tips:

  • await 展开

    await fn2(); console.log(2)
    //可以合并为 
    fn2().then(()=>{ console.log(2) })

Oliver
76 声望13 粉丝

Slow Done, Achieve More.