对阻塞操作的执行感到困惑 JavaScript 即(执行顺序)

Confused about blocking operation's execution JavaScript i.e (execution order)

async () => {
try {
  setTimeout(() => console.log('next task'), 0);
  await timeTakingFunc();
  console.log('after waiting for timetaking function');
} catch (error) {
  console.log(error.message);
}})();

输出:
等待计时功能后
下一个任务


不应该'next task'首先打印为timeTakingFunction();执行时间很长,超时只有 0 毫秒?

计时功能:

async function timeTakingFunc() {
return new Promise((resolve, error) => {
    for (let t = 1; t < 100000; t++) {
      for (let k = 1; k < 100000; k++) {
      }
    }
    resolve();
  });
};

您的 timeTakingFunc同步完成所有工作,原因有二:

  1. async 函数的代码在第一个 awaitreturn 之前是同步的。这样它就可以启动要异步完成的任何进程。
  2. 您传递给 new Promise 的执行程序函数是 运行 同步的,运行 在新承诺返回到进行调用的代码之前完成 - 出于相同的原因 async 函数同步启动。 (实际上,async 函数的开头,在第一个 awaitreturn 之前,直接类似于承诺执行函数的主体。)

所以这个函数实际上并没有什么异步的。

(旁注:没有理由在从不使用 await 并且显式创建其承诺的函数上使用 async。这是多余的。)

如果函数中有任何实际的异步工作几乎需要任何时间才能完成,您将看到您期望的输出顺序:

async function timeTakingFunc() {
    // This fetch fails, but it takes non-zero time to do so
    try {
        const response = await fetch("https://via.placeholder.com/150");
        if (response.ok) {
            await response.arrayBuffer();
        }
    } catch (e) {
    }
}
(async () => {
    try {
        setTimeout(() => console.log('next task'), 0);
        await timeTakingFunc();
        console.log('after waiting for timetaking function');
    } catch (error) {
        console.log(error.message);
    }
})();

但是使用该代码,timeTakingFunc 是同步的:

async function timeTakingFunc() {
    const p = new Promise((resolve, error) => {
        console.log("Start of executor function");
        for (let t = 1; t < 100000; t++) {
            for (let k = 1; k < 100000; k++) {}
        }
        console.log("End of executor function");
        resolve();
    });
    console.log("timeTakingFunc returning promise");
    return p;
};
(async () => {
    try {
        setTimeout(() => console.log('next task'), 0);
        await timeTakingFunc();
        console.log('after waiting for timetaking function');
    } catch (error) {
        console.log(error.message);
    }
})();

...JavaScript 引擎执行此操作:

  1. 设置计时器(在某些时候会将任务排队到 运行 计时器回调)
  2. 运行 timeTakingFunction 的同步部分(全部)直至完成
  3. [因为 await] 将当前任务的微任务队列中的微任务排队到 运行 代码的其余部分
  4. 到达当前任务的结尾
  5. 处理微任务队列
    • 运行代码的剩余部分,记录 "after waiting for timetaking function"
  6. 处理任务队列中的下一个任务,可能是定时器回调(如果不是,它很快就会出现在队列中)
    • 当定时任务为运行时,记录"next task"

这就是为什么你看到的顺序是同步的。