【问题标题】:async function javascript is not running in background?异步函数javascript不在后台运行?
【发布时间】:2021-05-02 17:42:38
【问题描述】:
console.log("1");
  console.log("2"); 
async function a() {
    for (let i = 0; i < 1000000000; i++) {}
    for (let i = 0; i < 1000000000; i++) {}
  }
  a().then(() => console.log("in then"));

  console.log("3!");

我想要的这个输出就是这个 1 2 3! 那时

但是 async 函数的行为是同步的,不会让 3!打印直到长循环执行完毕。我想如果使用 async 关键字,它会在后台运行里面的函数吗? 我基本上希望 2 个长循环在后台运行。只是想了解异步和等待。 谢谢。

编辑: 有人可以告诉我为什么这也可以同步工作吗??

  console.log("2");

  function lag(resolve) {
    for (let i = 0; i < 1000000000; i++) {}
    for (let i = 0; i < 1000000000; i++) {}
    console.log("in lag");
    return resolve;
  }
  async function a() {
    // console.log("its done");
    let a = await new Promise((resolve, reject) => lag(resolve));
  }
  a().then(() => console.log("in then"));

  console.log("3!"); ```

【问题讨论】:

  • for 是完全同步的。您正在执行一个 CPU 密集型操作,其中没有任何异步操作。去掉async关键字,完全没用。
  • "认为如果使用 async 关键字,它会在后台运行内部函数?" 不,这不是真的,而且从来没有这样工作过。 async 不会产生新进程。它允许你在正文中使用await,然后返回一个promise。它确实会自动处理 Promise 排序,但它仍然是单线程。

标签: javascript async-await


【解决方案1】:

async 函数(或承诺)没有任何东西可以让任何东西在后台运行。他们不会创建新线程或类似的东西。

async 函数在第一个 awaitreturn 之前是同步的。由于您的函数没有任何awaitreturn,因此它是完全同步的。

promise 的目的是观察已经异步的事情的完成,例如浏览器通过 HTTP 或计时器加载的事情。 async 函数的目的是为使用 Promise 提供语法,让我们编写代码的逻辑流程,而不是编写回调函数。他们都没有做任何异步的事情,或者将事情转移到不同的线程。

如果你想在后台运行一些东西,你可以创建一个工作线程并通过消息传递在它和主线程之间交换信息。在浏览器上是web workers。在 Node.js 中,它是 worker threads 模块。

在您的问题和 cmets 的答案中,您谈到了 async 函数似乎如何等待异步任务完成。事实上,函数的逻辑确实如此。但这确实是使用 Promise 的语法糖(非常非常好的语法糖,恕我直言)。我们来看一个async函数:

function delay(ms) {
    return new Promise(resolve => {
        setTimeout(resolve, ms);
    });
}

async function example() {
    // The function starts out synchronous, so that it can
    // start whatever inherently-asynchronous thing it does
    // (like calling `fetch`).
    console.log("[example] This is synchronous");

    // When execution reaches the first `await` or `return`,
    // the `async` function returns a promise. The synchronous
    // part of its work is now complete.
    await delay(10);

    // This code runs later, when/if the promise from `delay`
    // is settled.
    console.log("[example] This is asynchronous, but still on the main thread");

    // If you `throw` in an `async` function, it rejects the `async`
    // function's promise.
    if (Math.random() < 0.5) {
        throw new Error("Error thrown by `example`");
    }

    // The "return" value of an `async` function is the fulfillment
    // value of the promise the `async` function returned
    return 42;
}

console.log("[top] Calling `example`...");
const promiseFromExample = example();
console.log("[top] Back from calling `example`. Waiting for its promise to settle.");
promiseFromExample
.then((value) => {
    console.log(`[top] The promise from \`example\` was fulfilled with the value ${value}`);
})
.catch((reason) => {
    console.log(`[top] The promise from \`example\` was rejected with the rejection reason ${reason.message}`);
});
.as-console-wrapper {
    max-height: 100% !important;
}

运行几次,这样您就会看到满足和拒绝(每次运行都有 50/50 的机会)。该代码中除了主线程之外没有任何东西运行,只是在await 中,example 中的逻辑可以等待承诺解决。 delay 的承诺让我们观察计时器的完成,然后 example awaits 在继续其逻辑之前完成。

关键是:

  • Promise 不会使任何事情异步¹
  • Promises 和 async 函数不会将任何内容移出主线程
  • async 函数总是返回承诺
  • async 函数中的代码同步运行,直到第一个 awaitreturn
  • 来自async 函数的承诺通过函数的返回值实现,或因函数中出现的任何错误而被拒绝

¹ 好的,有一点需要注意:如果您使用 .then.catch(或 .finally)将回调连接到 Promise,则该回调将始终异步调用,即使 Promise 是已经解决了。

【讨论】:

  • FWIW,我在第 8 章详细介绍了 Promise,在我最近的一本书 JavaScript: The New Toys 的第 9 章详细介绍了 async 函数。如果您有兴趣,请在我的个人资料中链接。
  • 您好,谢谢,我有兴趣查看该章节。因此,如果我想要一组可能需要超过几个 cpu 滴答来执行异步运行的指令,我应该如何在 js 中实现它?通过使用等待?在我上面发布的代码中,我怎样才能使“3!”在“2”之后立即在控制台中打印?我了解网络工作者,但我注意到获取操作会阻止执行在它们下编写的指令异步工作,以避免使其下的指令等待。我能写出类似的指令吗?
  • @TheSlyOne - 让 CPU 密集型代码不阻塞主线程的唯一方法是将其放在另一个线程上——工作线程。无论是 promises 还是 async 函数都不会为您做到这一点。 fetch 是异步的原因是浏览器通过让 fetch 启动 进程来处理 HTTP 请求,返回一个承诺,然后在它有结果时履行或拒绝该承诺。使用fetchasync 函数基本上只是异步的,因为fetch 是。我已经扩展了答案以尝试说明这一点。编码愉快!
猜你喜欢
  • 2019-08-29
  • 1970-01-01
  • 2016-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-16
  • 1970-01-01
相关资源
最近更新 更多