根据动作有效负载的某些参数取消takeLatest任务

时间:2019-10-07 18:31:40

标签: redux-saga

我有一个动作(ACTION),其有效载荷格式为{a: …, b: …},下面是takeLatest代码。

yield takeLatest(ACTION, task);

现在,如果再次触发ACTION,任何先前的任务都会被取消,但是有没有办法根据参数取消此任务?

例如像下面这样

yield takeLatest(ACTION, task, (action1, action2) => (action1.a === action2.a))

现在,仅当'a'键的值相同时,任何先前的任务才会被取消。

一个简单的场景:

ACTION with payload {a: 1, b: 1} - Task 1 starts running


ACTION with payload {a: 2, b: 1} - Task 2 starts running and Task 1 isn't cancelled as the value of key 'a' doesn't match.


ACTION with payload {a: 1, b: 3} - Now, the Task1 is cancelled (if it's running) as the key 'a' matches with the first one.

另外,在相关说明中,如果作为takeLatest的一部分取消了任务,是否可以执行清理代码?

1 个答案:

答案 0 :(得分:1)

文档显示了如何使用较低级别的redux-saga效果实现takeLatest的示例,因此您可以执行类似的操作[1]。这将需要大量管理其他正在运行的任务的状态以及您希望设置的一般程度。

以面值作为示例,而忽略内存泄漏问题,则可以通过以下方式完成您描述的行为:

const takeLatestByKeyA = (patternOrChannel, saga, ...args) => fork(function*() {
  const tasks = {};
  while (true) {
    const action = yield take(patternOrChannel)
    if (tasks[action.payload.a]) {
      yield cancel(tasks[action.payload.a]) // cancel is no-op if the task has already terminated
    }
    tasks[action.payload.a] = yield fork(saga, ...args.concat(action))
  }
})

这假设payload.a是有效的对象密钥,并且您不关心清理tasks对象。如果需要,您可以添加代码来执行此操作,如果需要使用action.payload.a,则可以扩展辅助程序,使其更加通用,如果您将它用于其他用途而不只是比较action.payload.a,但我会留给您

对于在取消任务时运行代码,您可以按照文档[2]在finally块中进行操作:

function* myGenerator() {
  try {
    // your code
  } finally {
    if (yield cancelled()) {
      // do cleanup
    }
  }
}

[1] https://redux-saga.js.org/docs/api/#takelatestpattern-saga-args

[2] https://redux-saga.js.org/docs/advanced/TaskCancellation.html