【问题标题】:Why do the async keyword exists in JS?为什么JS中存在async关键字?
【发布时间】:2021-05-14 14:37:03
【问题描述】:

如果可以通过函数代码中的await关键字自动确定,为什么我每次都要在每个异步函数之前写async关键字?

function foo() { // This function is sync because it has no await keyword.
    return new Promise(function(resolve)
    {
        setTimeout(function(){resolve("RESULT")},1000)
    })
}

function bar() { // This function is sync because it has no await keyword.
    return foo()
}

function baz() { // This function is obviously async because it contains an await keyword.
  console.log(await bar())
}

baz()

此外,await 关键字也不需要,因为它会产生微妙的问题:

async function foo() {
  throw new Error('foo');
}

async function bar() {
  try {
    return foo();
  } catch (err) {
    console.log('caught with bar');
  }
}

bar(); // UnhandledPromiseRejectionWarning: Error: foo

它可以被 nowait 关键字代替,如果它是一个承诺,则默认解析每个函数调用:

async function foo() {
  throw new Error('foo');
}

async function bar() {
  try {
    return nowait foo(); // Now we clearly see what can cause the problem.
  } catch (err) {
    console.log('caught with bar');
  }
}

bar(); // UnhandledPromiseRejectionWarning: Error: foo

通过结合这两种方法,我们得到了一个干净的代码:

function foo() { // This function is async by default.
    return new Promise(function(resolve)
    {
        setTimeout(function(){resolve("RESULT")},1000)
    })
}

function bar() { // This function is deliberately sync because every function call in it is prepended by a nowait keyword.
    return nowait foo()
}

function baz() { // This function is also async because not EVERY function call is prepended by a nowait 
  console.log(nowait bar()) // Promise { <pending> }
  console.log(bar()) // "RESULT"
}

baz()

还可以同时使用sync/asyncawait/nowait 关键字来让每个人都开心。 在那个推理中我是否遗漏了一些重要的东西?

【问题讨论】:

  • 因为 javascript 的目标始终是保持事物的追溯兼容性。您提议的更改将破坏现有代码
  • console.log(nowait bar()) // Promise { &lt;pending&gt; } 为什么会得到这个输出? bar 不应该是同步的吗?
  • 这需要对应用程序中的所有代码(包括依赖项)进行完整的静态分析。为了确定所有可能的返回值类型,至少需要对代码进行最少的伪运行,这在像 JS 这样的动态语言中充其量是有问题的,特别是因为对象本身可以在运行时修改。这是一个寻找问题的解决方案,解决异步函数的低百分比。
  • 不相关,但语法高亮似乎不满意 function foo() 然后在行上添加注释,然后在下一行打开大括号。不知道为什么。看起来像一个错误。
  • @user619271 不,async 最明确地用于将函数描述为异步。不是相反。

标签: javascript asynchronous async-await


【解决方案1】:

我将从开发的角度来回答这个问题,而不是从技术的角度。

你明显错过的一件事是历史。

首先,当 JS 刚被开发时,Web 已经大不相同了。因此,您可能不喜欢某些解决方案,但这些决定是很久以前做出的。

在不破坏 90% 的网络的情况下,您无法从“非阻止”行为切换到“阻止”行为。你能想象这样的决定会引起开发者的愤怒吗?此外,JS 在用户浏览器上运行,我们无法控制用户更新它们。在发送 JS 脚本之前检查用户的浏览器版本不是一种选择。

现在,每个使用“await”的函数都需要返回一个 Promise,否则就没有任何意义。

这就是为什么引入“async”关键字的原因——你看这个函数,你第一眼就知道它返回一个 Promise,因为每个异步函数都返回一个 Promise。否则,您将不得不分析整个函数的代码并检查它是否包含任何“等待”操作。

【讨论】:

  • 据我所知,异步函数不仅可以返回承诺,这就是我在示例中引入 bar 函数的原因。
  • 现在我测试了一下,确实可以看出我错了!
  • 这是许多开发人员忘记的事情。异步函数 fn(){ 返回 "abc"; } 返回一个 Promise,自动解析为“abc”。
猜你喜欢
  • 1970-01-01
  • 2018-09-13
  • 2016-11-14
  • 1970-01-01
  • 1970-01-01
  • 2019-11-14
  • 2016-06-09
  • 1970-01-01
  • 2017-10-11
相关资源
最近更新 更多