Javascript 如何在redux saga中取消正在运行的网络请求?
我有一个传奇故事:Javascript 如何在redux saga中取消正在运行的网络请求?,javascript,reactjs,axios,redux-saga,Javascript,Reactjs,Axios,Redux Saga,我有一个传奇故事: function* sagaOne() { yield call(apiOne); yield call(apiTwo); yield call(apiThree); } function* sagaTwo() { try { yield all(users.map((user) => call(sagaOne, user)); yield put(successAction); } catch (err) {
function* sagaOne() {
yield call(apiOne);
yield call(apiTwo);
yield call(apiThree);
}
function* sagaTwo() {
try {
yield all(users.map((user) => call(sagaOne, user));
yield put(successAction);
} catch (err) {
yield put(errAction);
}
}
function* sagaThree() {
const task = yield fork(sagaTwo);
yield take(CancelAction);
yield cancel(task);
}
我的问题是-当sagaThree
开火时,它会分叉sagaTwo
。如果我调度cancel操作并且sagaOne
已处于更深的状态-apiOne
调用已解决并且apiTwo
已启动,则整个请求不会被取消
问题:当一个“更深层次的”、“嵌套的”任务(sagaOne)已经处于第二产量或第三产量时,如何正确地取消它?
总结:只有在启动后立即取消任务并且两个apiTwo中没有一个尚未启动时,取消才有效。如果进行得更深,取消就不起作用,每个sagaOne
中的每个调用都会解决
对于返回承诺结果的函数,您可以通过在承诺中附加[CANCEL]
来插入自己的取消逻辑
有关取消redux saga任务的详细信息
因此,我们需要使用一个方法来丰富axios返回的承诺,该方法将在取消时由redux saga调用,并将取消传出的xhr请求。您可以找到相关的axios文档
好的,让我们将此应用于api调用:
import axios from 'axios';
import { CANCEL } from 'redux-saga'
const CancelToken = axios.CancelToken;
const apiOne = () => {
const source = CancelToken.source();
const promise = axios.post('url', {
cancelToken: source.token
});
promise[CANCEL] = () => source.cancel();
return promise;
};
现在,一旦sagaOne
被取消,api调用也将被取消(当然,如果它还没有完成的话)
这是基本思想。您可以将公共逻辑提取到包装器或适配器中,所以不需要在每个api函数中都这样做。您还可以通过将executor函数传递给CancelToken
构造函数来创建一个cancel令牌。您正在询问如何取消api调用?这取决于api调用的实现方式。是fetch、xhr还是axios之类的库?取消sagas效果很好,请参见此处:。。。如果您谈论的是API请求本身,那么一旦调用了API,请求就会完成。这是一个浏览器的东西,不是saga的东西。@MartinKadlec不准确,一旦saga被取消,你们实际上可以取消api请求。如何做取决于什么是“api请求”@AlekseyL。这是一个邮寄请求。如何取消它?请为api调用添加示例代码,如上所述-这取决于您如何执行