宏任务与微任务 | 青训营笔记

60 阅读1分钟

宏任务与微任务 | 青训营笔记

这是我参与「第四届青训营 」笔记创作活动的的第2天

同步任务与异步任务

  1. JS分为同步任务和异步任务
  2. 同步任务在主线程上执行,形成执行栈
  3. 异步任务运行会先放到任务队列中
  4. 当执行栈中的任务执行完毕时,系统会去读取任务队列中的任务,将其添加到执行栈中去执行
  5. 如此往复也称事件循环

宏任务与微任务

宏任务包含:

  • script (可以理解为外层同步代码)
  • setTimeout
  • setInterval
  • UI交互事件
  • postMessage
  • MessageChannel
  • setImmediate(node环境)

微任无包含:

  • Promise.then
  • Object.observe
  • process.nextTick(node环境)
  • MutationObserver

宏任务和微任务执行顺序

  1. 执行宏任务,碰到微任务就将其放入微任务队列中
  2. 宏任务执行完毕后,立即执行微任务队列中的微任务
  3. 浏览器渲染
  4. 开始下一个宏任务

例题

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

// 1 4 8 5 6 7 3 2

console.log(1)
遇到setTimeout,将其放入宏任务队列
遇到Promise,执行console.log(4),将.then(console.log(5)...)放入微任务队列
console.log(8)
从微任务中取出.then(console.log(5)...),执行console.log(5)
将.then(console.log(6)...)放入微任务队列
将.then(()=>{Promis...})放入微任务队列
从微任务队列中取出.then(console.log(6)...),执行console.log(6)
从微任务队列中取出.then(()=>{Promis...}),将.then(console.log(7)...)放入微任务队列
从微任务队列中取出.then(console.log(7)...),执行console.log(7),微任务队列为空
从宏任务队列中取出任务(setTimeout),将.then(console.log(2))放入微任务队列
执行console.log(3)
从微任务队列中取出.then(console.log(2)...),执行console.log(2)