【前端每日一题】深入理解 JavaScript 事件循环之时序探究

273 阅读1分钟

请问下面代码的输出顺序是怎样的?

async function asyncFunction() {
  console.log('2. async function start');
  await Promise.resolve().then(() => {
    console.log('4. inside async function promise');
  });
  console.log('6. async function end');
}

console.log('1. script start');

setTimeout(() => {
  console.log('8. setTimeout');
}, 0);

Promise.resolve().then(() => {
  console.log('3. main thread promise');
});

asyncFunction();

nextTick(() => {
  console.log('5. nextTick');
});

console.log('7. script end');

解答:

  1. script start
  2. async function start
  3. main thread promise
  4. inside async function promise
  5. nextTick
  6. async function end
  7. script end
  8. setTimeout

解析:

  1. 同步代码总是首先执行。所以 script startscript end 会首先和最后输出。
  2. async/await 仍然是基于 Promise 的。在一个 async 函数内部,到达 await 表达式之前的部分会被立即执行。
  3. 当 JavaScript 主线程遇到 Promise 或 async/await 时,它会将其后续的 .thenawait 后的代码放入微任务队列。
  4. 当主线程上的同步任务完成后,它会开始处理微任务队列中的任务。
  5. Vue 的 nextTick 也是基于微任务的,但是会在当前微任务队列的最后执行。
  6. setTimeout 将回调放在宏任务队列中,只有当当前执行栈为空,并且微任务队列中没有任务时,才会开始执行。

因此,执行的顺序是如上所述。