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();