如何在redux中捕获处理ajax请求错误
youngwind opened this issue · 2 comments
youngwind commented
问题
以前用react+redux开发项目的时候,很少考虑到异步获取数据失败之后应该怎么办的问题。这次趁着做项目,在这方面做了一些探索。
以前的做法
//action.js
exports.requestPractice = function (practiceId) {
return {
type: ActionTypes.REQUEST_PRACTICE,
practiceId
};
};
exports.receivedPractice = function (practiceId, res) {
return {
type: ActionTypes.RECEIVE_PRACTICE,
practiceId: practiceId,
practice: res.data
};
};
exports.fetchPractice = function (practiceId) {
return function (dispatch) {
dispatch(exports.requestPractice(practiceId));
return fetch(`${Config.api}/practice?id=${practiceId}`, {
credentials: 'same-origin'
}).then(res => res.json())
.then(json => dispatch(exports.receivedPractice(practiceId, json)));
};
};
// 在container进行调用
componentDidMount:function(){
// 直接进行请求
fetchPractice(practiceId);
}
这样子简单粗暴的方法主要欠缺考虑下面两种情况:
- 网络错误导致请求失败
- 请求参数错误或者后端返回code状态码不为0
解决思路
- 在每个ajax请求的地方添加http状态码和code码的校验,如果不正确,则抛出错误。
- 在调用action方法的地方捕获处理错误
- 添加数据请求失败action,置fetchFail标志位为true,以表示上一次的数据请求失败
- 添加错误信息action和reducer,以存储错误提示,编写相应的统一错误提示component以显示错误提示。
现在的代码
// 请求部分添加校验
exports.fetchPractice = function (practiceId) {
return function (dispatch) {
dispatch(exports.requestPractice(practiceId));
return fetch(`${Config.api}/practice?id=${practiceId}`, {
credentials: 'same-origin'
}).then(Utils.checkStatus)
.then(res => res.json())
.then(Utils.checkCode)
.then(json => dispatch(exports.receivedPractice(practiceId, json)));
};
};
/**
* 检查fetch请求返回是否报错
* @param response
*/
exports.checkStatus = function (response) {
let {status, statusText} = response;
if (status >= 200 && status < 300) {
return response;
}
let error = new Error();
error = {
status,
msg: statusText
};
throw error;
};
/**
* 检查code状态码
* @param json
*/
exports.checkCode = function (json) {
let {code, msg} = json;
if (json.code === 0) {
return json;
}
let error = new Error();
error = {
status: 200,
code,
msg
};
throw error;
};
// 调用action的时候捕获错误
// 将捕获到的错误通过error action设置到store的error字段中
// 从而引发错误提示component的渲染显示
fetchPractice(practiceId).catch(err => {
fetchPracticeFail();
setErrorTip(err);
});
遗留问题
如果每次ajax数据请求错误都有统一的处理方式,是不是可以考虑将错误的捕获直接放在action里面呢?而不是每次调用的时候再捕获处理错误。但是这样又容易造成耦合,这个问题还需要思考实践一段时间。
jun-lu commented
nice ,
fetchPracticeFail
这个函数用来处理什么
用try catch是否也行
try{
fetchPractice(practiceId)
}catch(e){
setErrorTip(err);
}
ian4hu commented
可以每次发送action去请求数据时附带一个error的action作为payload,当出现错误时,dispatch这个action
dispatch(fetchData(params, fetchDataError('网络错误,无法读取'))