异步宏任务:
setTimeout,setInterval,requestAnimationFrame,script代码
异步微任务:
promise.then,process.nextTick(node环境),MutationObserver
- js是单线程的,js代码只能在一个线程上运行,但是任务有同步任务和异步任务之分,浏览器为了处理异步任务,就会模拟出多个线程,这多个线程就有优先级,分异步宏任务和异步微任务,微任务优先级 > 宏任务
- js需要实现异步,是因为异步代码执行时间过长,等待返回,会导致执行阻塞,页面内容长时间无法显示
- js通过 event loop 机制实现异步
- 由浏览器发起的异步请求是异步宏任务,js引擎发起的异步请求是异步微任务
- 宏任务里面仍然可以分同步任务和异步任务(比如 script)
事件循环: 从宏任务队列中取出一个宏任务1(script), 执行宏任务1内的同步代码, 遇到宏任务2(setTimeout),将宏任务2加入宏任务队列,遇到微任务(promise.then),将微任务加入微任务队列 等主线程上的任务执行结束,去微任务队列取任务执行,微任务队列取空后,去宏任务队列取任务执行,循环往复
案例1
结果:2 5 3 4 1
setTimeout(function timeout() {
console.log(1);
});
new Promise((resolve) => {
console.log(2);
resolve("a");
})
.then(function th1() {
console.log(3);
})
.then(function th2() {
console.log(4);
});
console.log(5);
案例2
结果: a, b, c ,before timeout, also before timeout,d
setTimeout((_) => console.log("d"));
new Promise((resolve) => {
resolve("p");
console.log("a");
}).then((_) => {
console.log("c");
Promise.resolve()
.then((_) => {
console.log("before timeout");
})
.then((_) => {
Promise.resolve().then((_) => {
console.log("also before timeout");
});
});
});
console.log("b");
案例3
结果:a,b,7,c,8,before timeout,also before timeout,d,9,11,12,2,4,5,13
setTimeout((_) => console.log("d"));
new Promise((resolve) => {
resolve("a");
console.log("a");
}).then((_) => {
console.log("c");
Promise.resolve()
.then((_) => {
console.log("before timeout");
})
.then((_) => {
Promise.resolve().then((_) => {
console.log("also before timeout");
});
});
});
console.log("b");
setTimeout(function () {
console.log("2");
new Promise(function (resolve) {
console.log("4");
resolve("4");
}).then(function () {
console.log("5");
setTimeout(() => {
console.log(13);
}, 0);
});
}, 1000);
new Promise(function (resolve) {
console.log("7");
resolve("7");
}).then(function () {
console.log("8");
});
setTimeout(function () {
console.log("9");
new Promise(function (resolve) {
console.log("11");
resolve("11");
}).then(function () {
console.log("12");
});
});