我设置了一个与 redux saga 一起使用的 React 项目,但由于某种原因,我无法取消正在运行的 saga/操作任务。预期是,在执行某些操作后(例如用户离开或单击按钮),正在运行的传奇将被取消。 try catch 取消的操作,但在传奇完全运行后不会发生:
function* fetchOverviewSaga(): SagaReturnType<any> {
try {
yield delay(5000);
console.log('still running');
const response = yield call(getOverviewData);
console.log('still running');
yield all([
put(updateTagsPendingState(false)),
put(updateTagsDataState(response.items)),
]);
} finally {
if(yield cancelled()) {
console.log('saga task canceled');
}
}
}
function* cancelOverviewSaga(): SagaReturnType<any> {
const runningAction = yield fork(fetchOverviewSaga);
yield cancel(runningAction);
}
function* overviewSaga() {
yield all([
takeLatest(startOverview, fetchOverviewSaga),
takeLatest(cancelOverview, cancelOverviewSaga)
]);
}
结果是,即使在分派(dispatch)操作进行取消 (cancelOverviewSaga) 后,fetchOverviewSaga 仍然运行,只有在它完全完成运行后,do 才会在 if(yield cancelled())
中被捕获。不确定这是否是实际行为,预计会在要求时取消。任何想法都非常受欢迎。
*编辑:
调用取消操作后,fetchOverviewSaga
似乎被取消,因为它确实记录了saga任务已取消
,但是剩下运行的是来自的 block >yield all([..]))
,查看控制台,问题可能出在该 block 内
*编辑2:
为了更好地说明行为:
- 调度 startOverview 操作
- 立即取消
- 日志:saga 任务已取消
- 5000ms 后(延迟在 fetchOverviewSaga 中完成)
- 日志:“仍然运行”x2 并从 fetchOverviewSaga 调度所有 yield
最佳答案
同一个传奇可以在多个实例中独立运行。所以例如如果你这样做
const task1 = yield fork(mySaga);
const task2 = yield fork(mySaga);
task1 === task2 // false
它将运行两个独立的 mySaga 实例,每个实例都有自己的任务。如果您取消其中一项,则不会取消另一项。因此,在 cancelOverviewSaga
中 fork 并立即取消 fetchOverviewSaga
saga 不会对因分派(dispatch) startOverview
操作而运行的 saga 产生任何影响。
在这种情况下,您可以使用例如实现目标的race
效果:
function* fetchOverviewSaga() {
try {
// your fetching logic ...
} finally {
if (yield cancelled()) {
console.log("saga task canceled");
}
}
}
function* startOverviewSaga() {
yield race([
call(fetchOverviewSaga),
take(cancelOverview),
]);
}
function* overviewSaga() {
yield takeLatest(startOverview, startOverviewSaga);
}
如果数组中的项目完成,则竞赛效果会等待一个项目,然后取消所有其他项目,因此:
- 如果在
fetchOverviewSaga
完成之前调度cancelOverview
操作,它将取消fetchOverviewSaga
- 如果
fetchOverviewSaga
在调度取消操作之前完成,它将停止等待取消操作。
关于reactjs - Redux Saga - 无法取消任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69717869/