在使用 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時,說明超時攔截成功
json