JavaScript是一门单线程语言,所谓单线程,就是指一次只能完成一件任务,如果在同个时间有多个任务的话,这些任务就需要进行排队,前一个任务执行完,才会执行下一个任务,这种存放待执行任务的队列就叫做事件队列。
然后js有一个机制分为宏任务和微任务,用来规范事件队列的执行顺序,宏任务和微任务分别存放在不同的event loop,这两个队列分别为macrotack queue和microtack queue.
Macrotack(宏任务):
script(整体代码)例如console.log、setTimeout、setInterval、setImmediateI/O、UI交互事件、postMessage、MessageChannel
Microtack(微任务):
await后面代码、Promise.then、MutationObserver、process.nextTick(Node环境)
注:
await做了什么
从字面意思上看await就是等待,await 等待的是一个表达式,这个表达式的返回值可以是一个promise对象也可以是其他值。
很多人以为await会一直等待之后的表达式执行完之后才会继续执行后面的代码,实际上await是一个让出线程的标志。await后面的表达式会先执行一遍,将await后面的代码加入到microtask中,然后就会跳出整个async函数来执行后面的代码。
由于因为async await 本身就是promise+generator的语法糖。所以await后面的代码是microtask
例子
setTimeout(function() {
console.log(1)
}, 0);
new Promise(function(resolve, reject) {
console.log(2)
for (var i = 0; i < 10000; i++) {
if(i === 10) {console.log(10)}
i == 9999 && resolve();
}
console.log(3)
}).then(function() {
console.log(4)
})
console.log(5);
输出答案为2 10 3 5 4 1
执行顺序为:同步执行的代码
console.log=promise>promise.nextTick>promise.then>setTimeout>setImmediate
promise( console.log(1)) cosole.log(2) // 1 2
console.log(2) promise(console.log(1)) // 2 1
宏任务 微任务 慢执行的宏任务分别代表:console promise settimeout
微任务:process.nextTick、MutationObserver、Promise.then catch finally
宏任务:I/O、setTimeout、setInterval、setImmediate、requestAnimationFrame