【问题标题】:Confused about blocking operation's execution JavaScript i.e (execution order)对阻塞操作的执行 JavaScript 感到困惑,即(执行顺序)
【发布时间】:2022-02-16 19:28:06
【问题描述】:
async () => {
try {
  setTimeout(() => console.log('next task'), 0);
  await timeTakingFunc();
  console.log('after waiting for timetaking function');
} catch (error) {
  console.log(error.message);
}})();

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


不应该首先将“下一个任务”打印为 timeTakingFunction();执行时间长,超时只有0ms?

计时功能:

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

【问题讨论】:

标签: javascript async-await promise


【解决方案1】:

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

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

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

(旁注:没有理由在从不使用 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"

这就是为什么你看到你看到的顺序,具有同步功能。

【讨论】:

  • 为了完全迂腐,在极少数情况下您仍然可以拥有“异步”timeTakingFunc 和 OP 看到的结果。它所需要的只是一个比超时队列或回调具有更高优先级的任务:jsfiddle.net/xbhLj3pt 更现实地,它也可以简单地使用分支,其中所有可能的异步函数确实返回已经解决的承诺,在我看来不那么“异步”,但可能...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多