原文地点:
await vs return vs return await作者:Jake Archibald
当编写异步函数的时刻,await
,return
,return await
三者之间有一些区分,从中拔取准确的体式格局是很主要的。
我们从下面这个异步函数最先:
async function waitAndMaybeReject(){
// 守候1秒钟
await new Promise(resolve => setTimeout(resolve, 1000));
// 抛一枚硬币
const isHeads = Boolean(Math.round(Math.random()));
if(isHeads) return 'yay';
throw Error('Boo!');
}
上面的函数会守候1秒钟后返回一个promise,然后有50%的时机胜利返回yay
或许抛出一个error。让我们用几种轻微差别的体式格局使用它。
直接挪用
async function foo() {
try{
waitAndMaybeReject();
}catch(e){
return 'caught';
}
}
在此处,假如挪用了foo
,返回的promise的状况一直都是resolved,值也永久是undefined,而且没有守候。
由于我们没有await,或许return waitAndMaybeReject()
的效果,所以我们没法对它做出任何回响反映。像如许的代码通常是毛病的。
Awaiting
async function foo(){
try{
await waitAndMaybeReject();
}catch(e){
return 'caught';
}
}
在此处,假如挪用了foo
,返回的promise将一直守候1秒钟,然后效果要么状况为resolved,值为undefined,要么状况为resolved,值为"caught"
。
由于我们守候了waitAndMaybeReject()
的返回值,所以它的rejection会被返回而且被抛出(throw),catch的代码块就会实行。但无论如何,假如waitAndMaybeReject()
没有报错而是顺遂实行,我们照旧没法对它的返回值做任何事情。
Returning
async function foo() {
try {
return waitAndMaybeReject();
}
catch (e) {
return 'caught';
}
}
在此处,假如挪用了foo
,返回的promise将一直守候1秒钟,然后效果要么是状况为resolved,值为"yaa"
,要么是状况是reject,抛出毛病Error('Boo!')
。
经由过程return waitAndMaybeReject()
这行代码,我们直接传递了它的返回效果,所以我们的catch代码块永久不会实行。
Return-awaiting
假如你想在try
代码块中获得带有准确返回值的resolved状况,在catch
中捕捉非常,那末准确的挑选就是return await
。
async function foo() {
try {
return await waitAndMaybeReject();
}
catch (e) {
return 'caught';
}
}
在此处,假如挪用foo
,返回的promise将一直守候1秒钟,然后效果要么是状况为resolved,值为"yay"
,要么是状况为resolved,值为"caught"
由于我们守候了waitAndMaybeReject()
的效果,所以它的非常rejecttion会被返回而且被抛出(throw),catch的代码块就会实行。假如waitAndMaybeReject()
顺遂实行没有报错,就返它的效果。
假如对上面的内容照样觉着疑心,那末将代码拆分红两个步骤来看可能会比较好明白:
async function foo() {
try {
// 守候 waitAndMaybeReject() 的效果来处理,
// 而且将 fullfill 的值赋给 fullfilledValue:
const fulfilledValue = await waitAndMaybeReject();
// 假如 waitAndMaybeReject() reject了,
// 我们的代码就会抛出非常,而且进入 catch 代码块的逻辑。
// 不然,这里的代码就会继承运转下面的语句:
return fulfilledValue;
}
catch (e) {
return 'caught';
}
}
Note: 在
try/catch
以外的代码块中实行
return await
是过剩的(如前所述,直接
return
即可),以至
Eslint还特地有划定规矩来检测这类场景,但是在
try/catch
代码块以内,Eslint就许可这类操纵。