首页 文章

redux-promise与Axios,以及如何处理错误?

提问于
浏览
10

所以,我看到一个错误,redux-promise给我回复错误:true,以及有效负载,但是一旦它击中了reducer ...对我来说,解耦请求和错误条件有点奇怪,似乎不当 . 当使用axios w / reduc-promise(中间件)时,还有一种处理错误情况的有效方法..这里是我所拥有的要点..

in action/
const request = axios(SOME_URL);

return {
   type: GET_ME_STUFF,
   payload: request
}

in reducer/
  const startState = {
     whatever: [],
     error: false
  }

  case GET_ME_STUFF:
     return {...state, startState, {stuff:action.payload.data, error: action.error? true : false}}

等...然后我可以处理错误..所以,我的api调用现在被分成两个单独的区域,这似乎是错误的......我必须在这里找到一些东西 . 我会想/在/ actions中我可以传递一个回调来处理一个新的动作等等 . 但是不能拆分它 .

6 回答

  • 1

    我've had to go through a similar situation. The challenge is that you likely won'能够评估承诺的结果,直到它在减速器上 . 你可以在那里处理你的异常,但它只是为了根据action.type返回适当的状态而不做任何其他操作 .

    所以,输入一个额外的中间件,redux-thunk . 它不返回一个对象,而是返回一个函数,它可以与promise共存 .

    http://danmaz74.me/2015/08/19/from-flux-to-redux-async-actions-the-easy-way/ 归档[here] . 从本质上讲,您可以在此处评估承诺,并在承诺结果到达减速器之前通过其他动作创建者进行分派 .

    在您的操作文件中,添加可处理成功和错误(以及任何其他)状态的其他操作创建者 .

    function getStuffSuccess(response) {
      return {
        type: GET_ME_STUFF_SUCCESS,
        payload: response
      }
    }
    
    function getStuffError(err) {
      return {
        type: GET_ME_STUFF_ERROR,
        payload: err
      }
    }
    
    export function getStuff() {
      return function(dispatch) {
        axios.get(SOME_URL)
          .then((response) => {
            dispatch(getStuffSuccess(response))
          })
          .catch((err) => {
            dispatch(getStuffError(err))
          })
      }
    }
    
    return null
    

    这大致就是如何将您的伪代码转换为链接中解释的内容 . 这样可以直接在您的操作创建器中评估promise,并根据操作约定 - > reducer - > state - >组件更新周期触发适当的操作和有效负载 . 我自己还是React / Redux的新手,但我希望这会有所帮助 .

  • 1

    接受的答案没有使用redux-promise . 由于问题实际上是关于使用redux-promise处理错误,我提供了另一个答案 .

    在reducer中,您应该检查action对象上是否存在error属性:

    // This is the reducer
    export default function(previousState = null, action) {
      if (action.error) {
        action.type = 'HANDLE_XHR_ERROR'; // change the type
      }  
      switch(action.type) {
        ...
    

    并更改操作的类型,为您为此设置的错误处理组件触发状态更改 .

    你可以在github上阅读更多关于它的信息here .

  • -2

    看起来您可以捕获发送调度的错误,然后在发生时进行单独的错误调度 . 这有点像黑客,但它的工作原理 .

    store.dispatch (function (dispatch) {
          dispatch ({
            type:'FOO',
            payload:axios.get(url)
          })
          .catch (function(err) {
            dispatch ({
              type:"FOO" + "_REJECTED",
              payload:err
            });
          });
      });
    

    在减速机中

    const reducer = (state=initialState, action) => {
      switch (action.type) {
        case "FOO_PENDING": {
          return {...state, fetching: true};
        }
        case "FOO_REJECTED": {
          return {...state, fetching: false, error: action.payload};
        }
        case "FOO_FULFILLED": {
          return {
            ...state,
            fetching: false,
            fetched: true,
            data: action.payload,
          };
        }
      }
      return state;
    };
    
  • 10

    仍然使用redux-promises你可以做这样的事情,我认为这是处理这个问题的一种优雅方式 .

    首先,在redux状态中设置一个属性,该属性将保存可能发生的任何ajax错误 .

    ajaxError: {},
    

    其次,设置一个reducer来处理ajax错误:

    export default function ajaxErrorsReducer(state = initialState.ajaxError, action) {
      if (action.error) {
        const { response } = action.payload;
        return {
          status: response.status,
          statusText: response.statusText,
          message: response.data.message,
          stack: response.data.stack,
        };
      }
      return state;
    }
    

    最后,创建一个非常简单的反应组件,如果有任何反应组件将呈现错误(我正在使用react-s-alert库来显示不错的警报):

    import React, { Component } from 'react';
    import { connect } from 'react-redux';
    import PropTypes from 'prop-types';
    import Alert from 'react-s-alert';
    
    class AjaxErrorsHandler extends Component {
    
      constructor(props, context) {
        super(props, context);
        this.STATUS_GATE_WAY_TIMEOUT = 504;
        this.STATUS_SERVICE_UNAVAILABLE = 503;
      }
    
      componentWillReceiveProps(nextProps) {
        if (this.props.ajaxError !== nextProps.ajaxError) {
          this.showErrors(nextProps.ajaxError);
        }
      }
    
      showErrors(ajaxError) {
        if (!ajaxError.status) {
          return;
        }
        Alert.error(this.getErrorComponent(ajaxError), {
          position: 'top-right',
          effect: 'jelly',
          timeout: 'none',
        });
      }
    
      getErrorComponent(ajaxError) {
        let customMessage;
        if (
          ajaxError.status === this.STATUS_GATE_WAY_TIMEOUT ||
          ajaxError.status === this.STATUS_SERVICE_UNAVAILABLE
        ) {
          customMessage = 'The server is unavailable. It will be restored very shortly';
        }
        return (
          <div>
            <h3>{ajaxError.statusText}</h3>
            <h5>{customMessage ? customMessage : ajaxError.message}</h5>
          </div>
        );
      }
    
      render() {
        return (
          <div />
        );
      }
    
    }
    
    AjaxErrorsHandler.defaultProps = {
      ajaxError: {},
    };
    
    AjaxErrorsHandler.propTypes = {
      ajaxError: PropTypes.object.isRequired,
    };
    
    function mapStateToProps(reduxState) {
      return {
        ajaxError: reduxState.ajaxError,
      };
    }
    
    export default connect(mapStateToProps, null)(AjaxErrorsHandler);
    

    您可以在App组件中包含此组件 .

  • 0

    这可能不是最好的方法,但它对我有用 . 我将组件的'this'作为var context传递给我 . 然后,当我得到响应时,我只执行我的组件上下文中定义的方法 . 在我的组件中,我有successHdl和errorHdl . 从那里我可以正常触发更多的redux动作 . 我检查了所有以前的答案,对于这样一个微不足道的任务似乎太令人生畏了 .

    export function updateJob(payload, context){
    
        const request = axios.put(UPDATE_SOMETHING, payload).then(function (response) {
            context.successHdl(response);
        })
        .catch(function (error) {
            context.errorHdl(error);
        });;
    
        return {
            type: UPDATE_SOMETHING,
            payload: payload,
        }
    }
    
  • 20

    不要使用redux-promise . 它过于复杂,实际上非常简单 .

    而是阅读redux文档:http://redux.js.org/docs/advanced/AsyncActions.html

    它将使您更好地理解如何处理这种交互,并且您将学习如何自己编写(优于)redux-promise .

相关问题