事件循环中并非只维护着一个队列,实际上是两个队列
- 宏任务队列:ajax、setTimeout、setinterval、DOM监听、UI Rendering等
- 微任务队列:Promise的then回调、Mutation Observe API、queueMicrotask
两个队列的优先级
- 所有同步任务都在主线程上执行,形成一个执行栈
- 主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件
- 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行
- 在执行任何一个宏任务以前(不是队列,是一个宏任务),都会查看微任务队列是否有任务需要清空,也就是宏任务执行以前,必须保证微任务是空的
- 主线程不断重复上面的步骤。
// 异步 宏任务
setTimeout(() => {
console.log("setTimeout")
},20)
// 异步 微任务
queueMicrotask(() => {
console.log("queueMicrotask")
})
// 异步 微任务
Promise.resolve().then(() => {
console.log("then1")
})
// 同步
console.log(1)
面试题练习:
// pr1 -- 2 -- then1 -- queueMicrotask -- then3 -- set2 -- set1 -- then2 -- then4
new Promise(function (resolve) {
console.log("pr1")
resolve()
}).then(function () {
console.log("then1")
})
setTimeout(() => {
console.log("set2")
},0)
console.log(2)
queueMicrotask(() => {
console.log("queueMicrotask")
})
new Promise(function (resolve) {
resolve()
}).then(function () {
console.log("then3")
})
setTimeout(() => {
console.log('set1')
new Promise(function (resolve) {
resolve()
}).then(function () {
console.log("then4")
})
console.log("then2")
},10)
// 注:await后面的代码等价于then回调
// script start -- async1 star -- async2 -- Promise1 --- script end
// async1 end -- Promise2 -- setTimeout
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
console.log("script start")
setTimeout(() => {
console.log("setTimeout")
}, 0)
async1()
new Promise((resolve) => {
console.log("Promise1")
resolve()
}).then(() => {
console.log("Promise2")
})
console.log("script end")