本文在簡書同步更新:https://www.jianshu.com/p/2df7c6e3b3c3
React Native的fetch請求本身自帶的超時時間比較長,也不能自定義超時時間,除非修改源碼(Android底層是由OkHttp實現)。在實際的App網絡連接當中,用戶是接受不了那麼長的網絡超時的,所以我們得自己封裝一個。在這裏我們可以合理使用Promise來解決這個問題。
一、Promise是什麼
所謂Promise,簡單說就是一個容器,裏面保存着某個未來纔會結束的事件(通常是一個異步操作)的結果。從語法上說,Promise 是一個對象,從它可以獲取異步操作的消息。Promise 提供統一的 API,各種異步操作都可以用同樣的方法進行處理。(該段話摘自阮一峯老師的ES6入門教程http://es6.ruanyifeng.com/#docs/promise)
Promise對象有個race方法,可以滿足我們的需求。Promise.race()方法接受一個Promise數組,數組裏面的每個Promise都可以在裏面同時運行,只要其中一個運行結束或者拋出錯誤,那麼Promise.race便會完成。
二、實現思路
根據Promise.race的特性,我們在Promise.race裏面添加兩個任務,一個是正常的網絡請求任務A,另外一個便是網絡延時任務B,網絡延時可以利用setTimeout方法實現。
這個時候會有三種情況出現:
1.A任務在8秒內完成(假定8秒超時),Promise.race任務正常結束。
2.超過8秒A任務仍然未完成,由B任務計時結束自動中斷Promise.race。
3.發生異常,Promise.race自動結束。
針對以上三種情況來設計網絡超時方案。
三、代碼實現
HttpUtil.js
//先定義延時函數
const delay = (timeOut = 8*1000) =>{
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject(new Error('網絡超時');
},timeOut);
})
}
//fetch網絡請求
const fetchPromise = (method,url, formData) =>{
return new Promise((resolve, reject) => {
fetch(url,{
method: method,
body:formData
}).then((response) => {
if (response.ok) {
return response.json();
} else {
reject(new Error('服務器異常'));
}
}).then((responseJson) => {
resolve (responseJson);
}).catch((err) => {
reject(new Error(err);
})
})
}
//race任務
const _fetch = (fetchPromise, timeout) => {
return Promise.race([fetchPromise,delay(timeout)]);
}
//post
const HttpPost = (url, formData,timeout = 8*1000) =>{
return _fetch(fetchPromise('POST', url, formData), timeout);
};
//get
const HttpGet = (url,timeout = 8*1000) =>{
return _fetch(fetchPromise('Get', url), timeout);
};
export {HttpPost ,HttpGet}
調用
import {HttpPost ,HttpGet} from HttpUtil;
//省略代碼。。。
let url = 'xxxxx'
let formData = new FormData();
formData.append("id",'123');
//timeout參數可以不寫,自動調用默認
HttpPost(url,formData).then((response) =>{
//do Something
}).catch((error) =>{
//網絡超時會在此拋出
console.warn(error)
})
let getUrl = 'https://www.baidu.com/s?'+'wd=' +'123';
HttpGet(getUrl).then((response) =>{
//do Something
}).catch((error) =>{
//網絡超時或網絡異常會在此拋出
console.warn(error)
})
四、總結
上面是實現思路,具體需要手動去編寫代碼實踐體會,主要運用到 Promise.race函數的功能。