什么是两者之间的区别?
return await foo()
并且
const t = await foo();
return t
return await foo()
并且
const t = await foo();
return t
基本上是因为 return await
是多余的。
从稍微高一些的层次来看,你实际上如何使用一个 async
函数:
const myFunc = async () => {
return await doSomething();
};
await myFunc();
任何async
函数都将返回一个Promise
,必须将其视为Promise
处理(可以直接作为Promise
处理,也可以同时使用await
进行处理)。await
,这是多余的,因为函数外部也会以某种方式await
它,所以没有理由不仅仅发送Promise
,让外部内容来处理它。function waitForN(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('Rejected'));
}, time);
});
}
async function testing() {
myPromise = waitForN(1000);
myPromise.catch(error => console.log(error));
return myPromise;
}
这将导致一个已捕获和一个未捕获的承诺。 - TigerBearreturn await
与返回Promise显着不同:您将获得一个堆栈跟踪(至少在现在的V8中是这样的)! - Mörretry{ return await foo() } finally { /* some code */ }
确实有意义。如果去掉await
,语义会变成"在获得承诺之后,无论发生什么都执行这个操作",而不是原本的意图,即"在承诺解决(完成或拒绝)之后执行这个操作"。很容易忽视这样的结构。 - programaths使用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();
}
foo();
Error: BEEP BEEP
at bar (<anonymous>:7:9)
at async foo (<anonymous>:2:10)
这确实提供了更好的错误跟踪,因此强烈鼓励您始终等待您的承诺。
此外,async/wait现在优于手写的promise代码:
async/await
现在优于手写的promise代码。关键要点是我们通过修补规范(而不仅仅是V8,而是所有JavaScript引擎)显着减少了异步函数的开销。来源
在v8.dev博客上阅读有关这些变更的更多信息:https://v8.dev/blog/fast-async#improved-developer-experience
const x = await foo()
比return await foo()
更好呢?这似乎没有解释清楚。 - AturSamsreturn
语句位于try ... catch
块内,那么在异步函数中使用return await
就不是无用的了。在这种情况下,使用await
将允许您立即处理任何错误。 - John Weiszawait
,调用函数的上下文是免费提供的)。 - Mörre因为你只需要
async function() {
return foo();
}
async function
的返回结果始终为 Promise
,无论您在函数体内返回确切的值还是另一个 Promise
对象。
foo()
而非return await foo()
。 - jmazinawait
,调用函数的上下文是“免费”可用的)。 - Mörreno-return-await
规则现已弃用。世界正在痊愈。return await
的有用性。让我添加一个演示,展示堆栈跟踪受到的影响。await
是一种误导性的“优化”尝试,只为了节省6个字符和一个微任务(编辑:ShortFuse刚刚证明在当前v8版本中实际上不是节省而是增加了一个微任务),却牺牲了堆栈跟踪、异常捕获、可重构性和代码一致性。简单来说,原则就是:如果你有一个异步调用,请使用await(除非你在做像并行处理或异步缓存这样的高级操作)。我相信我们应该坚持这个原则,并且始终使用return await
,并关闭那个no-return-await
的eslint规则。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);
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
function afunction() {
return asyncFun();
}
// with await
async function afunction() {
try {
return await asyncFun();
} catch(err) {
handleError(err);
// return error result;
}
}
哦,我认为很容易理解,当我们等待特定值以继续进程时,我们使用“await”,如果进程完成(查看返回),我们就不需要“await”语法了。
return await foo(); //is redundant
return foo(); //is the correct way
return foo();
。 - Igorconst x = await foo; return x
”呢? - AturSamsno-return-await
规则的解释。 - Bergireturn await
的优点是,已经在 V8 中启用了一个标志,您可以获得完整的异步堆栈跟踪。这是因为只要原始函数尚未完成,完整的堆栈仍然很容易重建。如果没有await
,如果直接返回 promise,则当调用堆栈中更深处的实际 promise 创建函数抛出异常时,该函数将永远消失。请查看 https://v8.dev/blog/fast-async 上的“零成本异步堆栈跟踪”。 - Mörre