【问题标题】:Why no-return-await vs const x = await?为什么 no-return-await vs const x = await?
【发布时间】:2017-12-02 00:48:16
【问题描述】:

有什么区别

return await foo()

const t = await foo();
return t

http://eslint.org/docs/rules/no-return-await

【问题讨论】:

  • 你真的不应该做第二个版本,因为它没有任何好处。正确的代码行是return foo();
  • @Igor 两个代码示例同样是多余的,只是编写方式略有不同。 return foo(); 是正确的。
  • 那么为什么不声明const x = await foo; return x应该避免呢?
  • @zehelvion - 可能是因为在编译时很难检测到这一点,但两个语句是等效的,应该避免。

标签: javascript async-await eslint


【解决方案1】:

return asyncFunc 和 return await Promise.resolve() 之间的显着区别在于,通过遵循第二种方法,如果异步函数内部出现错误,您可以捕获错误。

    function afunction() {
      return asyncFun();
    }
   
    // with await
    function afunction() {
     try {
         return await asyncFun();
     } catch(err) {
         handleError(err);
         // return error result;
       }
}

   
    

【讨论】:

    【解决方案2】:

    使用return await 在 Node.js、Chrome 和其他一些浏览器使用的 v8 引擎中确实有一些新引入的好处:

    v8 引入了一个 --async-stack-traces 标志,从 V8 v7.3 开始默认启用(Node.js v12.0.0)。

    此标志通过使用异步函数调用堆栈跟踪丰富错误堆栈属性来提供改进的开发人员体验。

    async function foo() {
      return bar();
    }
    
    async function bar() {
      await Promise.resolve();
      throw new Error('BEEP BEEP');
    }
    
    foo().catch(error => console.log(error.stack));
    
    
    Error: BEEP BEEP
        at bar (<anonymous>:7:9)
    

    请注意,通过调用return bar(); foo() 函数调用根本不会出现在错误堆栈中。将其更改为 return await bar(); 会提供更好的错误堆栈输出:

    async function foo() {
      return await bar();
    }
    
    Error: BEEP BEEP
        at bar (<anonymous>:7:9)
        at async foo (<anonymous>:2:10)
    

    这确实提供了更好的错误堆栈跟踪,因此强烈建议您始终等待您的承诺。

    此外,async/wait 现在优于手写承诺:

    async/await 现在的性能优于手写的 promise 代码。这里的关键点是我们通过修补规范显着降低了异步函数的开销——不仅在 V8 中,而且在所有 JavaScript 引擎中。 Source

    在 v8.dev 博客上阅读有关这些更改的更多信息:https://v8.dev/blog/fast-async#improved-developer-experience

    【讨论】:

    • 这似乎无法解释为什么const x = await foo()return await foo() 更好?
    • 好吧,如果你所做的只是 const x = 然后返回,它将能够检测到它,但我明白了。它完全一样,它不警告它的原因是它不想打扰检测更复杂的用例。
    • “在异步函数中,返回等待是无用的”——如果return 语句位于try ... catch 块中,则不会。在这种情况下,等待将允许您就地处理任何错误。
    • 如果您在当前版本的 V8(例如当前 node.js)上运行代码,"return await" 非常有用 - 在返回之前等待让 V8 编写完全异步。堆栈跟踪(没有“成本”,因为调用函数的上下文是“免费”可用的,因为await)。
    • @Bamieh v8.dev/blog/fast-async -- 向下滚动到“零成本”;请注意,该功能现在默认启用,例如在当前的 node.js 和 Chrome 版本中。
    【解决方案3】:

    基本上,因为return await 是多余的。

    从你实际使用async函数的更高层次来看:

    const myFunc = async () => {
      return await doSomething();
    };
    
    await myFunc();
    

    任何async 函数都将返回Promise,并且必须作为Promise 处理(直接作为Promise,或者也通过await-ing。

    如果你在函数内部await,这是多余的,因为外部函数也会以某种方式await,所以没有理由不只是发送Promise,让外部处理它。

    它在语法上没有错误或不正确,通常不会引起问题。这完全是多余的,这就是 linter 触发它的原因。

    【讨论】:

    • 我不确定“发送承诺并让外部事物处理它”是否 100% 正确。在我的测试中,通过直接返回 Promise 和等待然后返回值来创建一个新的 Promise:function waitForN(time) { return new Promise((resolve, reject) =&gt; { setTimeout(() =&gt; { reject(new Error('Rejected')); }, time); }); } async function testing() { myPromise = waitForN(1000); myPromise.catch(error =&gt; console.log(error)); return myPromise; } 这将导致一个被捕获和一个未被捕获的 Promise。
    • @TigerBear 实际上是您对myPromise.catch() 的调用导致它创建了一个新的Promise。与async/await 无关。调用.catch().then() 会创建一个新的Promise,这就是为什么通常链接它们并返回整个结果的原因。你应该做return myPromise.catch()
    • @samanime 请参阅我在 OPs 问题下的评论。由于在 V8 return await 中引入“零成本异步堆栈跟踪”与返回承诺明显不同:您将获得堆栈跟踪(至少在 V8 中,截至目前)!
    • @samanime 不在我的测试中。我得到一个堆栈跟踪。这正是他们声称的。如果您没有得到他们声称的内容,您应该提交报告。还要注意过于简单的测试、promise 及其基于“微任务”队列的实现如果不是真正异步的,则表现不一样。
    • @samanime 我指的是我之前的评论......无论你在测试什么,它都不是那个功能。它有效,我试过了——谷歌试过了。或者,如果不是在您的设置中,则存在错误。找到它或报告它。
    【解决方案4】:

    因为你可以

    async function() {
      return foo();
    }
    

    async function的返回结果总是Promise,不管你返回的是确切的值还是函数体内的另一个Promise对象

    【讨论】:

    • 这是最好的答案!!
    • 而不是return await foo(),只是return foo()
    • @YoniRabinovitch 不再。如果您在当前版本的 V8(例如当前 node.js)上运行代码,“返回等待”非常有用 - 在返回之前等待让 V8 组成完全异步。堆栈跟踪(没有“成本”,因为调用函数的上下文是“免费”的,因为 await)。
    猜你喜欢
    • 2021-08-25
    • 2022-11-07
    • 2021-08-30
    • 1970-01-01
    • 2017-10-26
    • 1970-01-01
    • 2016-05-12
    • 1970-01-01
    相关资源
    最近更新 更多