By Noxxxx from https://interview.noxxxx.com/?post_type=post&p=83 上山打老虎
欢迎分享与聚合,尊重版权,可以联系授权
事件循环是一个可以写好几篇文章的话题,在面试中大多是考察对异步的执行结果,本意是考察对事件循环的理解。
现象:
- macro-task(宏任务):
setTimeout
,setInterval
,setImmediate
,I/O
- micro-task(微任务):
process.nextTick
, 原生Promise(有些实现的promise将then方法放到了宏任务中),MutationObserver
- 先入先出的顺序再按宏任务和微任务进行执行
- promise(立即执行) > nextTick > then > setTimeout > setImmediate
例题1
async function test () {
console.log(1)
}
async function run () {
await test();
console.log(2)
}
run ()
new Promise((resolve, reject) => {
console.log(3);
resolve(4);
}).then(res => {
console.log(res)
})
new Promise((resolve, reject) => {
resolve();
console.log(5)
}).then(res => {
console.log(res, 6)
}).then((a) => {
console.log(7)
})
console.log('glob1');
setTimeout(function() {
console.log('timeout1');
process.nextTick(function() {
console.log('timeout1_nextTick');
})
new Promise(function(resolve) {
console.log('timeout1_promise');
resolve();
}).then(function() {
console.log('timeout1_then')
})
})
setImmediate(function() {
console.log('immediate1');
process.nextTick(function() {
console.log('immediate1_nextTick');
})
new Promise(function(resolve) {
console.log('immediate1_promise');
resolve();
}).then(function() {
console.log('immediate1_then')
})
})
process.nextTick(function() {
console.log('glob1_nextTick');
})
new Promise(function(resolve) {
console.log('glob1_promise');
resolve();
}).then(function() {
console.log('glob1_then')
})
setTimeout(function() {
console.log('timeout2');
process.nextTick(function() {
console.log('timeout2_nextTick');
})
new Promise(function(resolve) {
console.log('timeout2_promise');
resolve();
}).then(function() {
console.log('timeout2_then')
})
})
process.nextTick(function() {
console.log('glob2_nextTick');
})
new Promise(function(resolve) {
console.log('glob2_promise');
resolve();
}).then(function() {
console.log('glob2_then')
})
setImmediate(function() {
console.log('immediate2');
process.nextTick(function() {
console.log('immediate2_nextTick');
})
new Promise(function(resolve) {
console.log('immediate2_promise');
resolve();
}).then(function() {
console.log('immediate2_then')
})
})
Node v18.6.0 执行结果:
1
3
5
glob1
glob1_promise
glob2_promise
glob1_nextTick
glob2_nextTick
2
4
undefined 6
glob1_then
glob2_then
7
timeout1
timeout1_promise
timeout1_nextTick
timeout1_then
timeout2
timeout2_promise
timeout2_nextTick
timeout2_then
immediate1
immediate1_promise
immediate1_nextTick
immediate1_then
immediate2
immediate2_promise
immediate2_nextTick
immediate2_then
例题2
(()=>{
setTimeout(()=>{
console.log("1-1");
Promise.resolve().then(()=>{
console.log("1-2");
});
});
console.log("2-1");
Promise.resolve().then(()=>{
console.log("3-1");
setTimeout(()=>{
console.log("3-2");
});
});
new Promise(function(reslove) {
console.log('4-1');
setTimeout(() => reslove())
}).then(function() {
console.log('4-2');
})
})()
Chrome 111.0.5563.64 版本执行结果:
2-1
4-1
3-1
1-1
1-2
4-2
3-2
例题3:
console.log("start");
setTimeout(() => {
console.log("setTimeout1");
}, 0);
(async function foo() {
console.log("async 1");
await asyncFunction();
console.log("async2");
})().then(console.log("foo.then"));
async function asyncFunction() {
console.log("asyncFunction");
setTimeout(() => {
console.log("setTimeout2");
}, 0);
new Promise((res) => {
console.log("promise1");
res("promise2");
}).then(console.log);
}
console.log("end");
Chrome 111.0.5563.64 版本执行结果:
start
async 1
asyncFunction
promise1
foo.then
end
promise2
async2
setTimeout1
setTimeout2
例题4:
function double(num) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(2 * num)
}, 1000)
})
}
function test1 () {
const nums = [1, 2, 3];
nums.forEach(async x => {
const res = await double(x);
console.log(res);
})
}
test1();