先下结论
- 遇到宏任务并不是马上丢到宏任务队列。而是放到别的地方等待,谁先事件结束,就先放谁进入宏任务队列,然后再取出来。如果两个的定时任务的到期时间是一样的,那就把先执行的丢进宏任务队列。
- await 一层,后面的语句就是属于这个宏任务的微任务,并不是看到await马上把他丢到统一的微任务队列。await 一层 的外层如果还有await,那么后面的语句就属于这个宏任务的微任务的微任务。
- 注意微任务生成时间,并不是看到await就马上把他丢到相应宏任务的微任务队列。而是必须等await后面的东西执行完了,才丢到微任务队列。假设await后面是一个非promise对象或者执行方法,那就可以注册成微任务,丢进微任务队列。但如果await的方法是返回一个微任务Promise.resolve().then(),则把这个微任务丢到微任务队列。等待这个微任务被执行以后,才会把await后面的代码丢到微任务队列中。
一句话就是。遇到宏任务或微任务不是所有都马上丢进去相应的队列的。可以理解成:
- 宏任务就绪了,才丢进来。
- 注意微任务的所属宏任务,理解成,每个宏任务是应该有它专属的微任务。
- 重点。只有等await 的东西执行完毕,才会把其后的语句封装成微任务,丢到微任务队列
把第三点弄懂,这种题秒杀
后补样例
样例1
var sleep = function (time) {
console.log("sleep start");
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve();
}, time);
});
};
async function exec() {
await sleep(2000);
console.log("sleep end");
}
async function go() {
console.log(Date.now());
c1 = exec();
console.log("-------1");
c2 = exec();
console.log(c1, c2);
await c1;
console.log("-------2");
await c2;
console.log(c1, c2);
console.log(Date.now());
}
go();
答案1
1693339035562
sleep start
-------1
sleep start
Promise { } Promise { }
sleep end
-------2
sleep end
Promise { undefined } Promise { undefined }
1693339037577
样例2
var sleep = function (time) {
console.log("sleep start");
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(time);
}, time);
});
};
async function exec(time) {
let res=await sleep(time);
console.log("sleep end",res);
}
async function go() {
console.log(Date.now());
c2 = exec(5000);
console.log("-------1");
c1 = exec(1000);
console.log(c1, c2);
await c1;
console.log("-------2");
await c2;
console.log(c1, c2);
console.log(Date.now());
}
go();
答案2
1693340406572
sleep start
-------1
sleep start
Promise { } Promise { }
sleep end 1000
-------2
sleep end 5000
Promise { undefined } Promise { undefined }
1693340411579
样例3
console.log('script start')
async function async1() {
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2 end')
return Promise.resolve().then(()=>{
console.log('async2 end1')
})
}
async1()
setTimeout(function() {
console.log('setTimeout')
}, 0)
new Promise(resolve => {
console.log('Promise')
resolve()
})
.then(function() {
console.log('promise1')
})
.then(function() {
console.log('promise2')
})
console.log('script end')
答案3
script start
async2 end
Promise
script end
async2 end1
promise1
promise2
async1 end
setTimeout
快来验证一下是否全错吧!
浏览器和node环境事件循环的区别,一句话
- 浏览器的微任务是紧接着所属宏任务后执行完毕的。
- node环境是优先执行到时的宏任务,当前没有宏任务才去执行微任务。
所以,node中微任务执行是在宏任务执行的间隙中,并不紧跟着所属宏任务。而浏览器中是紧跟着的。不过,在node11以后,已经尽量和浏览器一致了。就是都是按第1点来。
还有就是node的任务队列会分得更多一点。
微任务队列:
next tick queue:process.nextTick
other queue:Promise.then、queueMicrotask
宏任务队列:
timer queue:setTimeout、setInterval
poll queue:IO
check queue:setImmediate
close queue:close
比如按照下面的顺序执行的:
- next tick mircotask queue
- other microtask queue
- timer queue
- poll queue
- check queue
- close queue