一,為什麼要用異步請求

異步請求是一種編程模式,允許代碼在等待某些操作(如網絡請求、文件讀取等)完成時繼續執行其他任務,而不需要阻塞整個程序。(JavaScript的單線程特性)

同步請求

異步請求

阻塞主線程

非阻塞,保持UI響應

用户界面凍結

更好的用户體驗

無法同時處理多個任務

可以並行處理多個任務

用户體驗差

更高的資源利用率

二,Await與Promise.then的區別

特性

Promise.then()

async/await

語法風格

鏈式調用

同步寫法

錯誤處理

.catch()方法

try/catch塊

可讀性

回調嵌套可能複雜

更像同步代碼

調試

可能更難追蹤

堆棧跟蹤更清晰

變量作用域

每個then有獨立作用域

同一作用域內

async/await學習:

  • async和 await 的基本使用

Promise.then學習:

  • promise中的.then方法

三,並行請求的實現

使用場景

  • 同時獲取商品信息、用户評價、庫存狀態
  • 並行請求多個數據源,快速渲染圖表
  • 同時加載用户信息、好友列表、動態內容
  • 並行獲取地圖數據、位置信息、周邊服務

實現方法

  1. 原生方法
  • Promise.all():當所有請求都成功時,返回一個包含所有請求結果的數組;如果有一個請求失敗,則立即返回失敗的原因。適用於需要所有數據才能繼續的場景。
  • Promise.allSettled():等待所有請求完成,不管成功還是失敗,返回一個對象數組,每個對象表示對應請求的結果。適用於需要處理部分失敗的場景。
  • Promise.race():返回最先完成的請求。適用於超時控制、競速場景。
  • Promise.any():返回第一個成功的請求。適用於多備份數據源、容錯場景。
  1. 使用async/await結合Promise.all()
async function fetchUserData() {
  try {
    // 假設我們有兩個API端點
    const userInfoPromise = fetch('https://api.example.com/user/info');
    const userPostsPromise = fetch('https://api.example.com/user/posts');

    // 使用Promise.all並行發起請求,並等待所有結果
    const responses = await Promise.all([userInfoPromise, userPostsPromise]);
    
    // 注意:fetch的響應體需要額外的方法(如.json())來讀取,它們也是異步的
    const dataArray = await Promise.all(responses.map(response => response.json()));
    
    console.log('用户信息:', dataArray[0]);
    console.log('用户帖子:', dataArray[1]);
  } catch (error) {
    // 處理任何一個請求發生的錯誤
    console.error('請求失敗:', error);
  }
}

fetchUserData();

當需要處理成百上千的請求時,直接使用 Promise.all 可能會導致性能問題或觸發瀏覽器的併發限制。一個常見的解決方案是分批處理。

  1. 使用第三方庫(如axios.all)
    使用 axios.all() 和 axios.spread()
    axios.all() 本質上就是 Promise.all(),它可以同時發起多個請求。axios.spread() 則是一個工具函數,用於將所有請求結果的數組合併到單個函數參數列表中,方便我們使用具名變量來接收結果