js的事件循环机制是为了实现异步
JavaScript是单线程语言,单线程就是说在同一时刻只能执行一个任务。而事件循环机制可以让JavaScript实现异步操作,不用等上一个异步函数完全执行完再执行下一个。
事件循环机制的具体执行
- 代码执行时,先执行同步任务,然后将异步任务放入相应的任务队列中等待执行。任务队列中的任务分为宏任务和微任务,分别存在宏任务队列和微任务队列。
- 当所有同步任务执行完毕,js会清空微任务队列中的微任务。
- 清空微任务队列后,js会去宏任务队列取出一个宏任务执行。
- 循环执行微任务和宏任务,直到两个队列都清空。
宏任务:setTimeout,setInterval,I/O操作 微任务:Promise,MutationObserver,process.nextTick
宏任务和微任务的区别
宏任务通常由浏览器或者node环境发起,适用于周期性任务。
微任务优先级高于宏任务,适用于需要尽快执行的任务。比如与数据处理相关的任务,可以放入微任务队列中,在下一轮页面渲染之前完成。
事件循环实例
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");
});
async1();
new Promise(function (resolve) {
console.log("promise1");
resolve();
}).then(function () {
console.log("promise2");
});
console.log("script end");
结果:
// script start
// settimeout 宏
// async1 start
// async2
// async1 end 微
// promise1 promise2 微
// script end
//
// async1 end
// promise2
// settimeout
console.log("1");
setTimeout(function () {
console.log("2");
process.nextTick(function () {
console.log("3");
});
new Promise(function (resolve) {
console.log("4");
resolve();
}).then(function () {
console.log("5");
});
});
process.nextTick(function () {
console.log("6");
});
new Promise(function (resolve) {
console.log("7");
resolve();
}).then(function () {
console.log("8");
});
setTimeout(function () {
console.log("9");
process.nextTick(function () {
console.log("10");
});
new Promise(function (resolve) {
console.log("11");
resolve();
}).then(function () {
console.log("12");
});
});
结果:
// 首先将两个settimeout中的函数视为一个整体
// 1
// settimeout_1宏
// 6微
// 7 8微
// settimeout_2宏
// 展开两个定时函数中的代码
// 1
// settimeout_1宏
// 6微√
// 7 8微√
// settimeout_2宏
// 6(微)
// 8(微)
// 2(settimeout_1宏)
// 4(settimeout_1宏)
// 3(settimeout_1宏)
// 5(settimeout_1宏)
// 9(settimeout_2宏)
// 11(settimeout_2宏)
// 10(settimeout_2宏)
// 12(settimeout_2宏)
const promise = new Promise((resolve, reject) => {
resolve("10");
})
.then(res => {
console.log("res1:", res); //res1
return 9;
})
.then(res => {
console.log("res2:", res); //res2: 9
return 8;
})
.then(res => {
console.log("res3:", res); //res3: 8
let promise2 = new Promise((resolve, reject) => {
resolve("p2");
}).then(res => {
console.log(res); //p2
setTimeout(function () {
console.log("setTimeout2");
}, 0);
});
});
console.log("aaa");
setTimeout(function () {
console.log("setTimeout1");
}, 0);
const promise1 = new Promise((resolve, reject) => {
console.log("p1");
resolve(989);
})
.then(res => {
console.log(res); //989
return 990;
})
.then(res => {
console.log(res); //990
return 991;
})
.then(res => {
console.log(res); //991
return 0;
});
结果
setTimeout(function () {
console.log("set1");
new Promise(function (resolve) {
resolve();
}).then(function () {
new Promise(function (resolve) {
resolve();
}).then(function () {
console.log("then4");
});
console.log("then2");
});
});
new Promise(function (resolve) {
console.log("pr1");
resolve();
}).then(function () {
console.log("then1");
});
setTimeout(function () {
console.log("set2");
});
console.log(2);
queueMicrotask(() => {
console.log("queueMicrotask1");
});
new Promise(function (resolve) {
resolve();
}).then(function () {
console.log("then3");
});
结果