前言:
在这之前,先介绍一下Js是一个单线程的语言,代码是从上到下执行的,遇到同步的代码,当有些代码是异步的时候,并不会停下来,如果停下来的话非常的耗时间,所以这个时候就有任务队列这个概念,当遇到异步的代码的时候,并不会等待异步代码执行完毕才执行下面的代码,而是将异步的代码放入任务队列里面,然后拿到主线程里面去执行。如此的循环下去被称为事件循环。
一.小试牛刀
setTimeout(function () {
console.log(1)
}, 0);
new Promise(function executor(resolve) {
console.log(2);
for (var i = 0; i < 10000; i++) {
i == 9999 && resolve();
}
console.log(3);
}).then(function () {
console.log(4);
});
console.log(5);
分析代码:
主线程: console.log(2); console.log(3); console.log(5);
异步: console.log(4)------微任务, console.log(1)------宏任务
因为: 微任务的优先级大于宏任务的优先级
最终执行的结果是: 2, 3, 5,4 ,1
图示:
二.测试测试
// 1、2、3、before timeout、alse before timeout、4、test
setTimeout(() => {
// #1
new Promise(resolve => {
resolve();
}).then(() => {
// #6
console.log('test');
});
console.log(4);
});
new Promise(resolve => {
// 一旦调用了 resolve 就把后面的 then 对应的回调添加到了微任务队列
resolve();
console.log(1)
}).then(() => {
// #2
console.log(3);
// 执行 Promise.resolve() 又把后面的 then 添加到了微任务队列
Promise.resolve().then(() => {
// #3
console.log('before timeout');
// 函数默认返回 undefined
// then 的函数其实返回默认的 Promise.resolve(undefined)
// return Promise.resolve(undefined) // 隐藏!!!
}).then(() => {
// #4
Promise.resolve().then(() => {
// #5
console.log('also before timeout')
})
})
})
console.log(2);
主线程: console.log(1), console.log(2);
任务队列:先执行微任务 : console.log(3); before timeout;also before timeout;
在执行定时器宏任务: console.log(4); 定时器的微任务:console.log('test');
最终执行的结果是:
1,2,3,before timeout,also before timeout,4,test。
三.变态测试
setTimeout(() => {
// #1
new Promise(resolve => {
resolve();
}).then(() => {
// #4
console.log('test');
});
console.log(4);
setTimeout(function () {
// #5
Promise.resolve().then(res => {
// #10
console.log(444);
})
})
Promise.resolve().then(res => {
// #6
console.log(888);
})
});
new Promise(resolve => {
resolve();
console.log(1)
}).then(() => {
// #2
console.log(3);
setTimeout(function () {
// #3
Promise.resolve().then(() => {
// #7:这一行确确实实打印了 before timeout,但是执行完毕后又产生了一个微任务
console.log('before timeout');
// return Promise.resolve(undefined)
}).then(() => {
// #8
Promise.resolve().then(() => {
// #9
console.log('also before timeout')
})
})
})
})
console.log(2);
代码分析:
主线程:console.log(1), console.log(2);
任务队列:console.log(3)------------微任务;剩下两个定时器是宏任务。
执行第一个定时器,console.log(4); 定时器的第一个微-test---定时器中的第二个微。同时又生成一个定时器,执行第二个定时器,before timeout,它的回调又产生了一个微任务打印also before timeout。执行最有一个定时器,打印444。
最终的执行结果是:1, 2,3,4,test,before timeout,also before timeout,444。
图示:
四.再测一测
Promise.resolve().then(() => {
// #1
Promise.resolve().then(r => {
// #2
console.log('a');
// return Promise.resolve(undefined)
}).then(r => {
// #4
console.log('h');
}).then(r => {
// #6
console.log('8');
}).then(r => {
// #8
console.log('99')
});
// return Promise.resolve(undefined)
}).then(r => {
// #3
console.log('44');
}).then(() => {
// #5
console.log('66')
}).then(() => {
// #7
console.log('7')
})
代码分析:
主线程:
执行这个异步的时候,同时产生了两个异步。 return Promise.resolve(undefined)。
任务队列:
console.log('a');
console.log('44');
主线程开始执行:
console.log('a'); console.log('44');
执行完a-----------产生新的微任务 console.log('h');
执行完44-------- 产生新的微任务 console.log('66')
主线程开始执行:console.log('h'); console.log('66')
如此交替下去.最终的执行结果是:
console.log('a');console.log('44');console.log('h'); console.log('66'); console.log('8');console.log('7'); console.log('99')。
图示:
五.继续测试
代码分析:
此时的任务队列: 产生微任务111---------222。
主线程:
111,
此时的微任务队列:
222
333
主线程继续执行:
222
微任务队列
333 444-666 555
主线程继续执行:
333 444 555 666
综上所述:
111,222,333,444,555,666
六.冲击最后一道题
function func(num) {
return function () {
// #1
console.log(num)
};
}
setTimeout(func(1));
async function async3() {
// # 这里调用 async4 确实直接打印了 5,但同时产生一个微任务
await async4();
// #2
console.log(8);
}
async function async4() {
console.log(5)
}
// !只要调马上就会执行
async3();
function func2() {
// #3
console.log(2);
async function async1() {
await async2();
// #6
console.log(9)
}
async function async2() {
console.log(5)
}
async1();
setTimeout(func(4))
}
setTimeout(func2);
setTimeout(func(3));
new Promise(resolve => {
console.log('Promise');
resolve()
})
.then(() => console.log(6)) // #4
.then(() => console.log(7)); // #5
console.log(0);
解析代码:
做这道题之前首先要知道await后面的代码是异步的。
第一遍走完:
主线程:
console.log(5)
console.log('Promise');
console.log(0);
宏任务:
setTimeout(func(1));
setTimeout(func2);
setTimeout(func(3));
微任务:
console.log(8);
console.log(6)
回调:
console.log(6)-----------console.log(7))
主线程要拿微任务去执行
主线程:
console.log(8);
console.log(6)
console.log(7))-----------回调也产生异步任务
目前输出的结果:
console.log(5)
console.log('Promise');
console.log(0);
console.log(8);
console.log(6)
console.log(7))-----------回调也产生异步任务
开始处理宏任务:
setTimeout(func(1));------------------1
setTimeout(func2);
console.log(2);
console.log(5)
产生微任务: console.log(9)
产生宏任务: setTimeout(func(4))
目前的宏任务: setTimeout(func(3)); setTimeout(func(4))
在去执行:
输出:1 ,2,5,9,3,4
最终执行的结果是:
console.log(5)
console.log('Promise');
console.log(0);
console.log(8);
console.log(6)
console.log(7))-----------回调也产生异步任务
1 ,2,5,9,3,4
图示: