宏任务与微任务
宏任务:script,setTimeout,setInterval,MessageChannel,I/O(文件,网络)相关API,DOM事件监听,setImmediate(Node.js)。
微任务:process.nextTick(Node.js)MutationObserver(浏览器),Promise.prototype.then()/catch()/finally()。
requestAnimationFrame是宏任务还是微任务?
有4种不同的情况:
宏任务里面新建宏任务:加入宏任务的队列中
运行宏任务时新建微任务:加入微任务的队列中
运行微任务时新建宏任务:加入宏任务的队列中
运行微任务时新建了微任务:新创建的微任务也会马上加入微任务队列,再下次宏任务之前一定会执行。
Promise与async函数
Promise语句属性微任务,也就是可以在一次事件循环中执行多个。直到微任务所在栈为空。但是Promise的构造函数是同步任务,
new Promise((resolve) => { … }).then(() => { … }) 在.then函数之前的部分都是同步任务。
面试中还常常出现async函数,本质上还是Promise的变种。在async函数中await语句之前,都是同步的(包括await语句),await语句之后的语句都属于await语句返回的Promise中的.then函数的回调中要执行的。有多个await语句同理等于多层Promise嵌套。
setTimeout函数使用setTimeout(fn, 0)时,并不是马上执行,因为是宏任务,所以,需要等同步任务完成之后,才能运行。最小间隔时间为4毫秒
一个简单的例子
使用 setTimeout和Promise.then和async/await函数当例子看看。
setTimeout(() => {
console.log('st1')
Promise.resolve().then(() => {
// 宏任务中新建微任务
console.log("pr2")
})
}, 0)
new Promise((resolve) => {
// 新建Promise代码为同步执行
setTimeout(() => {
console.log('st2')
})
resolve()
}).then(() => {
console.log("pr1")
Promise.resolve().then(() => {
// 微任务中新建微任务
console.log("pr3")
})
setTimeout(() => {
// 微任务中新建宏任务
console.log('st3')
})
})
console.log("st0")
上面这个例子的结果是:
st0
pr1
pr3
st1
pr2
st2
st3
参考资源:
我以为我很懂Promise,直到我开始实现Promise/A+规范
JavaScript 运行机制详解:再谈Event Loop
在阮一峰的博客中,使用执行栈和事件队列来描述微任务和宏任务。这两者的概念应该是等价的。