【问题标题】:Do I have to wait for void async functions?我必须等待无效的异步功能吗?
【发布时间】:2020-03-30 21:09:35
【问题描述】:

想象一下下面的 JavaScript:

async function f(x)
{
     var d = await NetworkRequest(x);
     d.ProcessResponse();
}

async function g()
{
    f(x);
    // Is network io completed now?

}

NetworkRequest 是一个真正的异步函数,一个异步完成的函数。问题 - 到 f() 返回时,是否可以确定 ProcessResponse 已完成?

如果g 没有被声明为异步怎么办 - 会有什么不同吗?

【问题讨论】:

  • 所有异步函数都会发生同样的事情,无论它们是否有返回值。 现在你会得到一个 Promise,但它会在 稍后完成。只是它是一个无效的承诺,但仍然是一个承诺。

标签: javascript asynchronous promise async-await


【解决方案1】:

异步函数看似阻塞,但实际上并非如此。它们返回一个解析为它们的返回值的承诺,因为它们仍在异步执行。如果你不返回任何东西,它只会返回一个不能解决任何问题的承诺。在g,你还是要await f(x)

【讨论】:

  • "异步函数看起来是阻塞的,但实际上不是" 我想说这完全相反,但只是在某些情况下。关于异步函数总是强调的一件事是它们阻塞并且总是“稍后”执行。只是,事实并非如此。至少不是“总是”——它们同步运行,直到达到await 或返回值。因此,它们看起来是非阻塞的,但在某些情况下,它们实际上是。
  • 在 async 函数内部,await 使事情像一个阻塞函数。因此,它们似乎处于阻塞状态。但是,javascript 的事件循环仍在触发并且外部函数同时运行,因此“实际上不是 [阻塞]”部分。
  • 但它不会阻塞。也许我与异步函数脱节,但我总是被告知它们不会阻塞,你不应该将await 视为实际上是等待现在直到完成。它们一直被解释为 Promises 之上的语法糖。这也是它们的工作方式。我从未见过任何解释或建议await 实际上阻止。如果有的话,我已经看到更多关于awaityield 工作方式相似的讨论。再次,它确实如此。
  • 我认为现在这是一个非常语义化的论点,但我会考虑停止函数的代码执行以等待承诺在某种程度上基本上是阻塞的。这就是我想说的。
【解决方案2】:

问题 - 到 f() 返回时,是否可以确定 ProcessResponse 已完成?

绝对不是。

f 被声明为async,它返回一个承诺并将控制权交还给g,它在等待另一个承诺时进入睡眠状态。

那是在ProcessResponse 被调用之前。

如果 g 没有被声明为 async 怎么办 - 会有什么不同吗?

没有


这可以证明:

const obj = {
    ProcessResponse: () => console.log("Process Response")
};

function NetworkRequest() {
    return new Promise( res => setTimeout(() => res(obj), 1000) );
}



async function f(x)
{
     console.log("f, before await");
     var f = await NetworkRequest(x);
     console.log("f, after await");
     f.ProcessResponse();
     console.log("f, after Process Response");
}

async function g()
{
    console.log("g, before f");
    f(x);
    console.log("g, after f");
}

const x = "global";
g();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多