Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何在redux中捕获处理ajax请求错误 #67

Open
youngwind opened this issue Apr 23, 2016 · 2 comments
Open

如何在redux中捕获处理ajax请求错误 #67

youngwind opened this issue Apr 23, 2016 · 2 comments
Labels

Comments

@youngwind
Copy link
Owner

youngwind commented Apr 23, 2016

问题

以前用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);
}

这样子简单粗暴的方法主要欠缺考虑下面两种情况:

  1. 网络错误导致请求失败
  2. 请求参数错误或者后端返回code状态码不为0

解决思路

  1. 在每个ajax请求的地方添加http状态码和code码的校验,如果不正确,则抛出错误。
  2. 在调用action方法的地方捕获处理错误
  3. 添加数据请求失败action,置fetchFail标志位为true,以表示上一次的数据请求失败
  4. 添加错误信息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
Copy link

jun-lu commented Nov 8, 2016

nice ,

fetchPracticeFail这个函数用来处理什么

用try catch是否也行

try{
   fetchPractice(practiceId)
}catch(e){
  setErrorTip(err);
}

@ian4hu
Copy link

ian4hu commented Nov 8, 2016

可以每次发送action去请求数据时附带一个error的action作为payload,当出现错误时,dispatch这个action

dispatch(fetchData(params, fetchDataError('网络错误,无法读取'))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants