React Native Fetch請求設置超時

本文在簡書同步更新: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函數的功能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章