[譯]await VS return VS return await

原文地址: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!')
通過返回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就允許這種操作。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章