fetch 請求超時處理

fetch 設置請求超時

在使用 js 自帶的 fecth 作網絡請求時,沒有提供例如$ajax 的超時選項,因此須要本身實現

多個fetch請求在網絡不穩定的狀況下,會佔用大量內存,由於當網速很慢的狀況下,fetch會一直等待,直到收到響應javascript

原理

使用Promise.race, Promise.race 的做用是哪一個 Promise 先返回結果則最終輸出這個 Promise 的返回值java

// 超時函數
const timeoutAction = timer => {
  return new Promise(reslove => {
    setTimeout(() => {
      // 實例化超時響應json數據
      const response = new Response(
        JSON.stringify({
          code: 1,
          msg: `timeout ${timer}s`
        })
      );
      return reslove(response);
    }, timer * 1000);
  });
};
const url = "/data.json"; // 請求的url

// 執行,超時控制在0秒,讓它永遠超時,方便觀察
Promise.race([timeoutAction(0), fetch(url)])
  .then(res => {
    return res.json();
  })
  .then(res => {
    if (res.code !== 0) {
      return alert(res.msg);
    } else {
      return console.log(res);
    }
  });

最終實現

上述代碼只是讓瀏覽器直到已經超時,而實際上的fetch請求還在繼續,因此要多作一步操做, 在超時的時候手動終止fetch請求
AbortController 用於手動終止一個或多個DOM請求,經過該對象的AbortSignal注入的Fetch的請求中。因此須要完美實現timeout功能加上這個就對了ajax

let controller = new AbortController();
let signal = controller.signal;
// 超時函數
const timeoutAction = timer => {
  return new Promise(reslove => {
    setTimeout(() => {
      // 實例化超時響應json數據
      const response = new Response(
        JSON.stringify({
          code: 1,
          msg: `timeout ${timer}s`
        })
      );
      reslove(response);
      controller.abort(); // 發送終止信號
    }, timer * 1000);
  });
};
const url = "/data.json"; // 請求的url

// 執行,超時控制在0秒,讓它永遠超時,方便觀察
Promise.race([
  timeoutAction(0),
  fetch(url, {
    signal: signal //設置信號
  })
])
  .then(res => {
    return res.json();
  })
  .then(res => {
    if (res.code !== 0) {
      return alert(res.msg);
    } else {
      return console.log(res);
    }
  });

目的驗證

當看到瀏覽器異步請求的狀態值爲canceled時,說明超時攔截成功
canceledjson

最終代碼

相關文章
相關標籤/搜索