JS事件循环,宏任内务,微任务,当前执行队列。
//同步任务1
function click1() {
//微任务
new Promise((resolve, reject) => {
resolve("click1引发的微任务");
}).then((val) => {
console.log(val);
});
//宏任务
setTimeout(() => {
console.log("click1引发的宏任务");
}, 0);
console.log("click1");
sleep(2000);
}
//同步任务2
function click2() {
console.log("click2");
//微任务
new Promise((resolve, reject) => {
resolve("click2引发的微任务");
}).then((val) => {
console.log(val);
});
//宏任务
setTimeout(() => {
console.log("click2引发的宏任务");
}, 0);
}
//参数n为休眠时间,单位为毫秒:
function sleep(n) {
var start = new Date().getTime();
// console.log('休眠前:' + start);
while (true) {
if (new Date().getTime() - start > n) {
break;
}
}
// console.log('休眠后:' + new Date().getTime());
}
//输出顺序
click1
click1引发的微任务
click2
click2引发的微任务
click1引发的宏任务
click2引发的宏任务
百度查询了js事件循环和异步队列的相关资料,以上代码用于测试验证。
1.事件任务
2.宏任务(setTimeout/setInterva等)
3.微任务(Promise)
测试浏览器:Chrome、Edge。
总结:
我将其分为:当前执行队列、宏任务队列、微任务队列。
1.事件触发时将事件任务加入当前执行队列开始执行,每完成一个任务后将执行微任务队列中所有任务。当前执行队列完成后更新UI。(测试发现DOM的操作在每个任务(方法/函数)结束后更新,但是UI只会在当前执行队列完成后才会更新)UI更新后本轮事件循环结束。
2.下轮事件循环,从宏任务队列中取出一个任务加入当前执行队列开始执行(如果有)。在执行过程中如果触发事件即加入当前执行队列,宏任务执行完毕后执行微任务队列,然后再开始执行事件任务。当前执行队列完成后更新UI结束本轮事件循环。
3.宏任务队列中,每轮事件循环仅取出一个宏任务执行。加入当前执行队列后和事件任务无异。当前执行队列每完成一个任务,就需要清理所有微任务。
随笔移植,原文地址:https://zhuanlan.zhihu.com/p/367363272