为什么 js 在浏览器中有事件循环
JS 是单线程的。如果一个线程操作一个 DOM 节点,另一个要删除这个 DOM 节点,会冲突。所以如果想执行一些异步的代码,要通过 event-loop 来处理
两种任务
宏任务
整体代码
定时器
I/O
微任务
Promise.then() 中的回调
MutationObserver
为什么要有微任务
因为宏任务永远是先进先出,但是有的任务优先级高需要立即执行。
执行规则
先执行宏任务之后去执行其中遇到的所有微任务和这些微任务中的微任务。完成后再去下一轮宏任务。
Node 中的事件循环
例题1
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
async function async2() {
console.log("async2");
}
console.log("script start");
setTimeout(function(){
console.log('setTimeout');
},0)
async1()
new Promise(function(resolve){
console.log("promise1");
resolve()
}).then(function(){
console.log("promise2");
})
console.log("script end");
/*
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
*/
// await async2() await 后的相当于放在 new Promise 中属于同步的,直接执行,他下面的代码相当于放在 .then 里
例题2
console.log("start");
setTimeout(() => {
console.log("children2");
Promise.resolve().then(() => {
console.log("children3");
});
}, 0);
new Promise(function (res, rej) {
console.log("children4");
setTimeout(function () {
console.log("children5");
res("children6");
}, 0);
}).then((res) => {
console.log("children7");
setTimeout(() => {
console.log(res);
}, 0);
});
/*
start
children4
进行下一轮宏任务,进入上面的定时器,把children3放进微任务,本轮宏任务结束
children2
输出微任务中的children3
children3
下一轮宏任务进入下面的定时器
children5
children7
children6
*/
// 注意 没有 resolve 时 .then 不会加入微任务