redux-promise 与 axios 以及如何处理错误?
redux-promise with Axios, and how do deal with errors?
所以,我看到一个错误,redux-promise 将 error: true 和 payload 一起递给我,但那是一旦它到达 reducer...对我来说,将请求和错误条件分离是一个有点奇怪,似乎不合适。在使用带有 reduc-promise(中间件)的 axios 时,处理错误情况的有效方法是什么..这是我所拥有的要点..
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 中我可以传入一个处理新动作等的回调,但不能拆分它。
我也遇到过类似情况。挑战在于,在 promise 到达 reducer 之前,您可能无法评估它的结果。您 可以 在那里处理异常,但这不是最佳模式。从我读过的内容来看,reducers 仅用于 return 基于 action.type 的适当状态,不做任何其他事情。
所以,输入一个额外的中间件,redux-thunk。它 return 不是一个对象,而是一个函数,它可以与 promise 共存。
在 http://danmaz74.me/2015/08/19/from-flux-to-redux-async-actions-the-easy-way/ [archived here] 上解释得很好。本质上,您可以在此处评估 promise,并在 promise 结果到达 reducers 之前通过其他 action creator 进行分派。
在您的动作文件中,添加额外的动作创建者来处理成功和错误(以及任何其他)状态。
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
这大致是关于如何将伪代码转换为 link 中解释的内容。这会直接在你的 action creator 中评估 promise,并向你的 reducers 发出适当的动作和有效负载,这遵循 action -> reducer -> state -> component update cycle 的约定。我自己对 React/Redux 还是很陌生,但我希望这会有所帮助。
不要使用 redux-promise。它使一些实际上非常简单的事情变得过于复杂。
改为阅读 redux 文档:http://redux.js.org/docs/advanced/AsyncActions.html
它会让你更好地理解如何处理这种交互,你将学习如何自己编写一些(比)redux-promise 的东西。
这可能不是最好的方法,但对我有用。我将组件的 'this' 作为 var 上下文传递。然后当我得到响应时,我只执行在我的组件上下文中定义的方法。在我的组件中,我有 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,
}
}
看起来您可以在进行分派的地方捕获错误,然后在发生错误时进行单独的错误分派。这有点 hack,但它有效。
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;
};
接受的答案没有使用 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) {
...
并更改操作类型,触发您为此设置的错误处理组件的状态更改。
您可以在 here github 上阅读更多相关信息。
仍然使用 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 组件,如果有任何错误,它将呈现错误(我正在使用 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 组件中。
所以,我看到一个错误,redux-promise 将 error: true 和 payload 一起递给我,但那是一旦它到达 reducer...对我来说,将请求和错误条件分离是一个有点奇怪,似乎不合适。在使用带有 reduc-promise(中间件)的 axios 时,处理错误情况的有效方法是什么..这是我所拥有的要点..
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 中我可以传入一个处理新动作等的回调,但不能拆分它。
我也遇到过类似情况。挑战在于,在 promise 到达 reducer 之前,您可能无法评估它的结果。您 可以 在那里处理异常,但这不是最佳模式。从我读过的内容来看,reducers 仅用于 return 基于 action.type 的适当状态,不做任何其他事情。
所以,输入一个额外的中间件,redux-thunk。它 return 不是一个对象,而是一个函数,它可以与 promise 共存。
在 http://danmaz74.me/2015/08/19/from-flux-to-redux-async-actions-the-easy-way/ [archived here] 上解释得很好。本质上,您可以在此处评估 promise,并在 promise 结果到达 reducers 之前通过其他 action creator 进行分派。
在您的动作文件中,添加额外的动作创建者来处理成功和错误(以及任何其他)状态。
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
这大致是关于如何将伪代码转换为 link 中解释的内容。这会直接在你的 action creator 中评估 promise,并向你的 reducers 发出适当的动作和有效负载,这遵循 action -> reducer -> state -> component update cycle 的约定。我自己对 React/Redux 还是很陌生,但我希望这会有所帮助。
不要使用 redux-promise。它使一些实际上非常简单的事情变得过于复杂。
改为阅读 redux 文档:http://redux.js.org/docs/advanced/AsyncActions.html
它会让你更好地理解如何处理这种交互,你将学习如何自己编写一些(比)redux-promise 的东西。
这可能不是最好的方法,但对我有用。我将组件的 'this' 作为 var 上下文传递。然后当我得到响应时,我只执行在我的组件上下文中定义的方法。在我的组件中,我有 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,
}
}
看起来您可以在进行分派的地方捕获错误,然后在发生错误时进行单独的错误分派。这有点 hack,但它有效。
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;
};
接受的答案没有使用 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) {
...
并更改操作类型,触发您为此设置的错误处理组件的状态更改。
您可以在 here github 上阅读更多相关信息。
仍然使用 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 组件,如果有任何错误,它将呈现错误(我正在使用 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 组件中。