事件循环训练题

题目

console.log("script start"); // 宏任务

async function asyncFunc() {
  console.log("asyncFunc start");
  await Promise.resolve(); // 等待Promise解决
  console.log("asyncFunc promise resolved");
}

asyncFunc(); // 调用async函数

setTimeout(function () {
  console.log("setTimeout"); // 宏任务
}, 0);

Promise.resolve()
  .then(function () {
    console.log("promise1"); // 微任务
    return new Promise((resolve) => {
      setTimeout(() => {
        console.log("setTimeout in promise1"); // 宏任务
        resolve();
      }, 0);
    });
  })
  .then(function () {
    console.log("promise2"); // 微任务
  });

Promise.resolve().then(function () {
  console.log("promise3"); // 微任务
});

console.log("script end"); // 宏任务

输出

script start
asyncFunc start
script end
promise1
promise3
asyncFunc promise resolved
undefined
setTimeout
setTimeout in promise1
promise2

解答

1. 为什么在输出asyncFunc start后会直接输入script end?

  • 这是因为JavaScript的事件循环和任务队列的工作方式。当你调用一个异步函数时,它会立即开始执行,但是当遇到await关键字时,它会将后面的代码(在这个例子中是console.log("asyncFunc promise resolved"))放入微任务队列,并立即返回控制权给主线程。

  • 在主线程中,console.log("script end")是下一个要执行的语句,所以它会立即被执行。只有当主线程的所有同步任务都完成后,才会开始执行微任务队列中的任务。因此,console.log("asyncFunc promise resolved")会在console.log("script end")之后被执行。

  • 这就是为什么你会看到"asyncFunc start"后面立即输出"script end",然后才输出"asyncFunc promise resolved"。

2. “在主线程中,console.log("script end")是下一个要执行的语句,所以它会立即被执行。”为什么不是setTimeout或者是Promise.resolve?

  • 这是因为JavaScript的事件循环机制和任务队列的工作方式。JavaScript有一个主线程用于执行同步任务,以及一个任务队列用于存放异步任务。当主线程的所有同步任务都执行完毕后,才会去任务队列中取出任务来执行。

  • 在你的代码中,console.log("script end")是一个同步任务,因此它会被立即执行。而setTimeoutPromise.resolve().then都是异步任务,它们会被放入任务队列中,等待主线程的同步任务都执行完毕后再执行。

  • 此外,setTimeoutPromise.resolve().then产生的任务分别属于宏任务微任务。在每一轮事件循环中,主线程首先会执行所有的微任务,然后再执行一个宏任务。因此,即使setTimeoutPromise.resolve().then在代码中的位置在console.log("script end")之前,它们也会在console.log("script end")之后执行。

posted @ 2024-05-29 15:59  脆皮鸡  阅读(10)  评论(0编辑  收藏  举报