Redux 传奇:如何从另一个没有启动它的任务中取消一个任务?

问题描述:

我正在阅读这篇文章关于取消Redux 传奇.基本上他们的例子是这样的:

I'm reading this article on cancelling tasks in Redux saga. Basically the example they have goes like this:

function* main() {
  yield call(task1);
  yield cancel(task1);
}

function* task1() {
  <...>
}

这里 main 可以取消 task1 因为它调用了它.在我的代码中,我正在运行这样的函数:

Here main can cancel task1 because it called it. In my code I'm running the functions like this:

function* task1() {
  <...>
}

function* task2() {
  yield cancel(task1);
}

function* main() {
  takeLatest(actionCreator1, task1);
  takeLatest(actionCreator2, task2);
}

取消task2 中的task1 不起作用,大概是因为task2 没有调用task1.有谁知道我该如何解决这个问题?

Cancelling task1 in task2 doesn't work, presumably because task2 didn't invoke task1. Does anyone know how I can approach this?

解决方案可能是让 main 自己实现类似于 takeLatest 的东西,但使用额外的逻辑来取消其他任务.

The solution is probably to have main do it's own implementation of something similar to takeLatest, but with extra logic to cancel the other task.

如果您只希望 action2 执行额外的取消操作,则它看起来像这样:

If you only want action2 to do the extra cancel, then it will look something like this:

function* main() {
  let firstTask;
  let secondTask;
  while (true) {
    const action = yield take([actionCreator1, actionCreator2]);
    if (firstTask) {
      // Always cancel task 1, whether we got action 1 or action 2
      yield cancel(firstTask);
    }
    if (action.type === "the type of action 1") {
      firstTask = yield fork(task1, action);
    } else {
      if (secondTask) {
        // Only cancel task 2 if we got action 2
        yield cancel(secondTask);
      }
      secondTask = yield fork(task2, action);
    }
  }
}

如果你想让两个动作都取消两个任务,那就简单一点:

If you want both actions to cancel both tasks, it's a bit simpler:

function* main() {
  let task;
  while (true) {
    const action = yield take([actionCreator1, actionCreator2]);
    if (task) {
      yield cancel(task);
    }
    if (action.type === "the type of action 1") {
      task = yield fork(task1, action);
    } else {
      task = yield fork(task2, action);
    }
  }
}