[譯]await VS return VS return await

司南free發表於2018-11-23

原文地址: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函式中使用await來呼叫foo函式】

直接呼叫

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就允許這種操作。

來源:https://juejin.im/post/5bf7baa1e51d4532206d5d92

相關文章