【发布时间】:2016-09-19 13:14:27
【问题描述】:
我正在使用 redux-thunk 中间件构建一个 React/Redux 应用程序来创建和处理 Ajax 请求。我有一个经常触发的特殊 thunk,我想在触发新请求之前取消任何以前启动的 Ajax 请求。这可能吗?
【问题讨论】:
标签: reactjs redux redux-thunk
我正在使用 redux-thunk 中间件构建一个 React/Redux 应用程序来创建和处理 Ajax 请求。我有一个经常触发的特殊 thunk,我想在触发新请求之前取消任何以前启动的 Ajax 请求。这可能吗?
【问题讨论】:
标签: reactjs redux redux-thunk
一种方法是通过为这些请求提供随机 id 并在处理结果之前检查其状态来将这些请求标记为已取消。
这样做的方法是在您的第一次调度中(在 thunk 内)为此调用分配随机 id,并在处理结果之前在 reducer 中检查它。
const actionId = Math.random();
dispatch({type: AJAX_LOAD_CONST, id:actionId })
当你想取消所有请求时使用
dispatch({type:HANDLE_AJAX_RESPONSE, id:actionId, results: json })
当您要处理结果时,别忘了发送您的 id
在reducer中有这样的东西:
function reducer(state = initialState, action) {
switch (action.type) {
case actions.AJAX_LOAD_CONST:
return Object.assign({}, state, { ajax: state.ajax.concat(action.id) });
case actions.CANCEL_ALL_AJAX:
return Object.assign({}, state, { ajax: [] });
case actions.HANDLE_AJAX_RESPONSE:
if (state.ajax.includes(action.id) {
//return state reduced with action.results here
}
return state;
}
}
如果您使用 XMLHttpRequest 或其包装器之一(JQuery?),您还可以自己存储请求并调用 request.abort()。如果你使用新的 fetch api,你就没有这种奢侈,因为 Promise 缺乏这种行为。
【讨论】:
我最近遇到了同样的问题,我不得不取消挂起或过时的异步 redux 操作。我通过创建一个取消 redux 操作中间件来解决它。
在 redux 中,我们有中间件的概念。因此,当您发送请求时,它将通过中间件列表。一旦 api 响应,它的响应将通过许多中间件,然后到达 redux 存储并最终到达您的 UI。
现在假设我们已经编写了一个取消中间件。 api请求发起时会经过这个中间件,api响应时api响应也会经过这个中间件。
redux 中的每个 api 请求都关联一个 action,每个 action 都有一个 type 和一个 payload。
编写一个中间件,每当一个 api 请求完成时,它都会存储相关的动作类型。与它一起,它存储一个标志,说明是否放弃此操作。如果再次触发类似类型的操作,请将此标志设为 true,表示丢弃此操作。由于此 api 请求的丢弃标志已设置为 true,因此当上一个操作的 api 响应出现时,从中间件发送 null 作为响应。
查看此博客以获取有关此方法的详细信息。
https://tech.treebo.com/redux-middlewares-an-approach-to-cancel-redux-actions-7e08b51b83ce
【讨论】:
如果你使用jquery ajax,你可以让你的action creator返回promise,它会被dispatch函数返回,然后就可以中止它。这是一个例子:
function doSomething() {
return (dispatch) => {
return $.ajax(...).done(...).fail(...);
}
}
componentDidMount(){
this.previousPromise = this.props.dispatch(doSomething());
}
somefnct() {
this.previousPromise.abort();
}
【讨论】: