Axios 同步等待 API 示範(Promise)

平時在使用 axios 呼叫 API 時,應該會直接往下執行,會等到 API 執行完畢後才會依情況執行 then, catch, finally 等區塊。
    
console.log("start");

axios.get("https://localhost:7183/api/user/1")
    .then((response) => console.log(response.data))
    .catch((error) => console.log(error))
    .finally(() => console.log("finally"));
    
console.log("end");

// 順序:
// start
// end
// {id: 1, name: 'Ruyut'} // API 取回的資料
// finally
    

如果要等到 axios 結束後再繼續,也就是 end 要最後被執行,可以使用「同步」,在 axios 前面加上 await 關鍵字,等到結束後再繼續。不過不能直接使用 await 關鍵字,因為 await 關鍵字只能在 async 函式和模組的最上層內部使用,不然會出現下面的錯誤:
    
Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules
    

所以我們可以透過在外面包一層 function 來執行,在前面加上 await 後就會等待 axios 的 get 確實結束後才繼續執行下一行了
    
async function getUserData() {

    console.log("start");
    
    await axios.get("https://localhost:7183/api/user/1")
        .then((response) => console.log(response.data))
        .catch((error) => console.log(error))
        .finally(() => console.log("finally"));
        
    console.log("end");
}

getUserData();

// 輸出:
// start
// {id: 1, name: 'Ruyut'} // API 取回的資料
// finally
// end
    

那假設今天要呼叫三個 API ,且要等到這三個 API 結束後再繼續處理或是顯示資料該怎麼做?當然可以直接一個一個按順序執行:
    
async function getUserData() {

    console.log("start");
    
    await axios.get("https://localhost:7183/api/user/1")
        .then((response) => console.log(response.data))
        .catch((error) => console.log(error))
        .finally(() => console.log("finally"));
    await axios.get("https://localhost:7183/api/user/2")
        .then((response) => console.log(response.data))
        .catch((error) => console.log(error))
        .finally(() => console.log("finally"));
    await axios.get("https://localhost:7183/api/user/3")
        .then((response) => console.log(response.data))
        .catch((error) => console.log(error))
        .finally(() => console.log("finally"));
        
    console.log("end");
}

getUserData();

// 輸出:
// start
// {id: 1, name: 'Ruyut'} // API 取回的資料
// finally
// {id: 2, name: '大頭'} // API 取回的資料
// finally
// {id: 3, name: '老吳'} // API 取回的資料
// finally
// end
    

不過,在假設這三個 API 沒有順序性的情況下,會要等第一個結束才能第二個,第二個結束才能第三個,會花很多時間。筆者在這個測試 API 中寫了一個等待,API 會等 2 秒後才回應,上面的範例中共耗時 6.053 秒。

那有沒有辦法加快呢? 因為反正是等三個 API 執行完,誰先誰後都沒問題,只要等他們都跑完在執行後面的即可,那我們可以使用 Promise 來一次執行多件事情,等到全部都結束後再執行後面的程式碼:
    
    
async function getUserData() {

    console.log("start");


    const promises = [
        axios.get("https://localhost:7183/api/user/1"),
        axios.get("https://localhost:7183/api/user/2"),
        axios.get("https://localhost:7183/api/user/3"),
    ];

    const responses = await Promise.all(promises);


    const user1 = responses[0].data;
    const user2 = responses[1].data;
    const user3 = responses[2].data;

    console.log(user1);
    console.log(user2);
    console.log(user3);

    console.log("end");

}

getUserData();

// 輸出:
// start
// {id: 1, name: 'Ruyut'} // API 取回的資料
// {id: 2, name: '大頭'} // API 取回的資料
// {id: 3, name: '老吳'} // API 取回的資料
// end
    

共耗時 2.018 秒,幾乎可以說是和呼叫一個 API 的時間相同!當然大部分呼叫 API 時都不會這麼久,不過還是要保持良好的開發習慣,善用並行處理。

不過唯一要注意的就是如果要呼叫的 API 太多,記得一定要分開,免得到時候老闆問說:「最近公司伺服器一直被 DDoS ,你有沒有什麼頭緒?」

留言