react-native 中的网络请求才用的是fetch 请求,其没有请求超时的设置,也不能中断请求。为此通过才用Promise 的race 进行了封装处理
Promise.race 是竞赛模式,Promise.race([p1, p2, p3]),里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。因此请求超时的原理就是在规定的时间内超时的异步处理返回相应的结果,此时如果网络请求还没有完成则也不再返回!
/**
* post、get请求
* url : 请求地址
* data : 参数(Json对象)
* callback : 回调函数
* */
fetch_request(url,params="") {
let header = {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=UTF-8'
}
let promise = null;
if (params==null||params == '') {
promise = new Promise((resolve, reject) => {
fetch(url, {method: "GET", headers: header})
.then(res => {
if (res.status !=200) {
//上报请求错误的日志
this.reportHttpLog(url,res.status,res.statusText)
}
return res;
})
.then(response => response.text())
.then(responseData => resolve(responseData))
.then(err => reject(err))
.catch((err)=>reject(err))
})
} else {
promise = new Promise((resolve, reject) => {
fetch(url, {method: "POST", headers: header, body: params})
.then(res => {
if (res.status !=200) {
this.reportHttpLog(url,res.status,res.statusText)
}
return res;
})
.then(response => response.text())
.then(responseData => resolve(responseData))
.then(err => reject(err))
.catch((err)=>reject(err))
})
}
return this.warp_fetch(promise);
},
/**
* 创建两个promise对象,一个负责网络请求,另一个负责计时,如果超过指定时间,就会先回调计时的promise,代表网络超时。
* @param {Promise} fetch_promise fetch请求返回的Promise
* @param {number} [timeout=120000] 单位:毫秒,这里设置默认超时时间为2分钟
* @return 返回Promise
*/
warp_fetch(fetch_promise, timeout = 120000) {
let timeout_fn = null;
let abort = null;
//创建一个超时promise
let timeout_promise = new Promise(function (resolve, reject) {
timeout_fn = function () {
reject('网络请求超时');
};
});
//创建一个终止promise
let abort_promise = new Promise(function (resolve, reject) {
abort = function () {
reject('请求终止');
};
});
//竞赛
let abortable_promise = Promise.race([
fetch_promise,
timeout_promise,
abort_promise,
]);
//计时
setTimeout(timeout_fn, timeout);
//终止
abortable_promise.abort = abort;
return abortable_promise;
},
request:function (url, data="", successCallBack, errCallBack,returnAll=false) {
//判断url是否是正确
if(!this.isDataValid(url)||url.indexOf("undefined")==0||url.indexOf("null")==0||url.indexOf("http://")!=0){
errCallBack&&typeof(errCallBack)=="function"&&errCallBack("url请求地址错误");
return null;
}
let promise=this.fetch_request(url,data)
promise.then((responseText)=>{
try{
if(returnAll){
successCallBack&&typeof(successCallBack)=="function"&&successCallBack(eval("("+responseText+")"));
}else{
//统一处理返回结果,针对登录令牌失效的进行统一处理
......
}
}catch(err){//处理返回内容是html格式解析错误的情况
this.SyntaxError(url,responseText,err,errCallBack);
}
}).catch((err)=>{
this.SyntaxError(url,err,err,errCallBack);
})
//此处返回promise 方便在js页面中可以直接调用promise中终止请求的方法
return promise;
},
代码中调用:
let promise=NetUtil.request(url,JSON.stringify(data),successCallBaack, errCallBack)
//中断请求
promise.abort()