前几天收到一个需求,就是在网络请求超时时,弹出一个toast告知用户“网络请求超时,请稍后重试!”。当接到这个需求时,一开始并没有觉得有多麻烦,直接在fetch请求时设置一下timeout属性就行了。于是乎就去React Native的开发文档中去找,可结果却让人“很难过”,居然没有找到,心里不免嘀咕“又掉到坑里面了”。
好吧,既然没有timeout属性就只能自己去想办法解决了。经过一段时间的思考,初步确定了三种解决方案:
- 通过和原生的交互来实现网络请求超时的功能;
- 把fetch重新封装一下,加上timeout的功能,参考博文;
- 使用其他的网络库,文档中说React Native中已经内置了XMLHttpRequest API(也就是俗称的ajax);
在项目中我选择了第二种方法,具体的实现如下:
//Http.js
export default fetchers = {
post:(url, body = {}) => {
return _fetch(fetch_promise(url, body = {}), 60000);
}
}
function _fetch(fetch_promise, timeout) {
var abort_fn = null;
var abort_promise = new Promise((resolve, reject) => {
abort_fn = function() {
reject('abort promise');
};
});
var abortable_promise = Promise.race([
fetch_promise,
abort_promise
]);
setTimeout(function(){
abort_fn();
}, timeout);
return abortable_promise;
}
function fetch_promise(url, body = {}) {
return new Promise((resolve, reject) => {
fetch(url,{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=UTF-8',
},
}).then((response) => {
return response.json();
}).then((jsonData) => {
resolve(jsonData);
}).catch((err) => {
reject(err);//这里可以使用resolve(err),将错误信息传回去
if (err.message === 'Network request failed'){
console.log('网络出错');
} else if (err === 'abort promise'){
console.log('请求超时');
}
})
})
}
/*
* 此巧妙之处在于Promise.race()的使用
*/
这是目前项目中初步解决网络超时的方法,第一种和第三种方案还没有来得及去实现,后期如果有时间实现会在此后加上。如果发现有需要修改的地方或是好的建议,也可以留言告知,大家相互交流相互提高嘛!
网友评论
function fetch_promise(url, body = {}) {
return new Promise((resolve, reject) => {
_fetch(fetch(url,{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=UTF-8',
},
})).then((response) => {
return response.json();
}).then((jsonData) => {
resolve(jsonData);
}).catch((err) => {
reject(err);//这里可以使用resolve(err),将错误信息传回去
if (err.message === 'Network request failed'){
console.log('网络出错');
} else if (err === 'abort promise'){
console.log('请求超时');
}
})
})
}
我的方案跟你不一样,结果是能出来的。我是看有些人报的错(只有报network request failed,并且黄色提示框一直提示有reject未处理)跟我编程过程中的报错很相似,给一个解决问题的方案而已。
引用:
import fetchers from '../../utils/Http';
调用:
fetchers.post(`${queryStrings.QUERY_ECHARTS_DATAS + reqRefs}`, '')
.then(data => dispatch(receiveInvestmentP11(data)));
import fetchers from '../../utils/Http';
调用:
fetchers.post(`url`, '{params}')
.then(data => console.log(data)));
Promise.race([
this.fetchPromise(url, oldPassword, newPassword),
timerPromise
]).then(
(res) => console.log(res), //接收上面resolve中的参数
(error) => {console.log(res)} //接收上面reject中的参数
);