简体   繁体   English

为什么 no-return-await vs const x = await?

[英]Why no-return-await vs const x = await?

What is the difference between和有什么区别

return await foo()

and

const t = await foo();
return t

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

Basically, because return await is redundant.基本上,因为return await是多余的。

Look at it from a slightly higher level of how you actually use an async function:从你实际如何使用async函数的更高层次来看它:

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

await myFunc();

Any async function is already going to return a Promise , and must be dealt with as a Promise (either directly as a Promise , or by also await -ing.任何async函数都将返回一个Promise ,并且必须作为Promise处理(直接作为Promise ,或者也通过await -ing。

If you await inside of the function, it's redundant because the function outside will also await it in some way, so there is no reason to not just send the Promise along and let the outer thing deal with it.如果你在函数内部await ,它是多余的,因为外部的函数也会以某种方式await它,所以没有理由不只是发送Promise并让外部处理它。

It's not syntactically wrong or incorrect and it generally won't cause issues.它在语法上没有错误或不正确,通常不会引起问题。 It's just entirely redundant which is why the linter triggers on it.这完全是多余的,这就是 linter 触发它的原因。

Using return await does have some newly introduced benefits in v8 engine used by Node.js, Chrome and a few other browsers:在 Node.js、Chrome 和其他一些浏览器使用的 v8 引擎中,使用return await确实有一些新引入的好处:

v8 introduced a --async-stack-traces flag which as of V8 v7.3 is enabled by default (Node.js v12.0.0). v8 引入了一个--async-stack-traces标志,从 V8 v7.3 开始默认启用(Node.js v12.0.0)。

This flags provides an improved developer experience by enriching the Error stack property with async function calls stack trace.此标志通过使用异步函数调用堆栈跟踪丰富错误堆栈属性来提供改进的开发人员体验。

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)

Note that by calling return bar();请注意,通过调用return bar(); foo() function call does not appear at all in the error stack. foo()函数调用根本不会出现在错误堆栈中。 Changing it to return await bar();将其更改为return await bar(); gives a much better error stack output:提供更好的错误堆栈输出:

async function foo() {
  return await bar();
}
foo();

Error: BEEP BEEP
    at bar (<anonymous>:7:9)
    at async foo (<anonymous>:2:10)

This indeed does provide much better error stack tracing, hence it is HIGHLY encouraged to always await your promises.这确实提供了更好的错误堆栈跟踪,因此强烈建议始终等待您的承诺。

Additionally, async/wait now outperformes hand written promises:此外,async/wait 现在优于手写承诺:

async/await outperforms hand-written promise code now. async/await现在优于手写的 Promise 代码。 The key takeaway here is that we significantly reduced the overhead of async functions — not just in V8, but across all JavaScript engines, by patching the spec.这里的关键点是,我们通过修补规范显着降低了异步函数的开销——不仅在 V8 中,而且在所有 JavaScript 引擎中。 Source资源

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

Because you can just因为你可以

async function() {
  return foo();
}

The returned result of async function always is Promise , no matter you return the exact value or another Promise object inside the function body async function的返回结果总是Promise ,无论你返回的是确切的值还是函数体内的另一个Promise对象

It seems many are debating the usefulness of return await in the comments.似乎很多人在评论中争论return await的有用性。 Let me add a demonstration that shows how the stacktrace is affected.让我添加一个演示,说明堆栈跟踪是如何受到影响的。

In my opinion, skipping await is a misguided attempt at some sense of "optimization", saving 6 characters and a microtask (EDIT: ShortFuse just showed that it is actually not saving but adding a microtask in current v8 ) at the cost of stacktraces, try-catches, refactorability and code consistency.在我看来,跳过await是在某种“优化”意义上的错误尝试,以堆栈跟踪为代价保存 6 个字符和一个微任务(编辑: ShortFuse 刚刚表明它实际上不是在保存,而是在当前 v8 中添加了一个微任务),尝试捕获、可重构性和代码一致性。 The rule of the thumb is simple: have an async call, await it (unless you are doing fancy stuff like parallelism or async caching).经验法则很简单:有一个异步调用,等待它(除非你正在做一些花哨的东西,比如并行或异步缓存)。 I believe we should stick to the rule of thumb and always use return await , and switch off that no-return-await eslint rule.我相信我们应该坚持经验法则并始终使用return await ,并关闭那个no-return-await eslint 规则。

little demo:小演示:

 async function main() { console.log("\nStatcktrace with await shows testStackWithAwait:"); await testStackWithAwait().catch(logStack); console.log("\nStatcktrace without await hides testStackWithoutAwait:"); await testStackWithoutAwait().catch(logStack); console.log("\nFinally happens before try block ends without await:"); await testFinallyWithoutAwait(); } async function fnThatThrows() { await delay(1); throw new Error(); } async function testStackWithoutAwait() { return fnThatThrows(); // bad } async function testStackWithAwait() { return await fnThatThrows(); // good } async function fnThatLogs() { await delay(1); console.log('inside'); } async function testFinallyWithoutAwait() { try { return fnThatLogs(); // bad } finally { console.log('finally'); } } function logStack(e) { console.log(e.stack); } function delay(timeout, value) { return new Promise(resolve => { setTimeout(() => { resolve(value); }, timeout); }); } main().catch(console.error);

On Chrome 103 on Windows I get the following logs:在 Windows 上的 Chrome 103 上,我得到以下日志:

Statcktrace with await shows testStackWithAwait:
Error
    at fnThatThrows (https://stacksnippets.net/js:23:9)
    at async testStackWithAwait (https://stacksnippets.net/js:31:10)
    at async main (https://stacksnippets.net/js:14:3)

Statcktrace without await hides testStackWithoutAwait:
Error
    at fnThatThrows (https://stacksnippets.net/js:23:9)
    at async main (https://stacksnippets.net/js:16:3)

Finally happens before try block ends without await:
finally
inside

The significant difference between return asyncFunc and return await Promise.resolve() is by following the second approach you can catch an error if something wrong inside async function. return asyncFunc 和 return await Promise.resolve() 之间的显着区别在于,通过遵循第二种方法,如果 async 函数内部出现问题,您可以捕获错误。

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

   
    

Oh I think is easy to understand, we put "await" when we wait for a specific value in order to continue a process, if the process is finished (look at the return), we don't need the await syntax anymore so.哦,我想很容易理解,当我们等待一个特定的值以继续一个过程时,我们放了“await”,如果这个过程完成了(看看返回),我们就不需要 await 语法了。

return await foo(); //is redundant
return foo(); //is the correct way

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM