![](/img/trans.png)
[英]When invoking `call` in redux-saga, is the async action scheduled to be run?
[英]Cancel a saga when an action is dispatched with redux-saga
在调度START动作时,我为秒表React组件启动计时器:
import 'babel-polyfill'
import { call, put } from 'redux-saga/effects'
import { delay, takeEvery, takeLatest } from 'redux-saga'
import { tick, START, TICK, STOP } from './actions'
const ONE_SECOND = 1000
export function * timerTickWorkerSaga (getState) {
yield call(delay, ONE_SECOND)
yield put(tick())
}
export default function * timerTickSaga () {
yield* takeEvery([START, TICK], timerTickWorkerSaga)
yield* takeLatest(STOP, cancel(timerTickWorkerSaga))
}
/*
The saga should start when either a START or a TICK is dispatched
The saga should stop running when a stop is dispatched
*/
从我的组件调度STOP
动作时,我无法停止传奇。 我试过在我的工作者传奇中使用cancel
和cancelled
效果:
if(yield(take(STOP)) {
yield cancel(timerTickWorkerSaga)
}
以及第一个代码块中的方法,我试图阻止来自观看服务的传奇。
看起来这里发生了一些事情:
cancel
副作用将Task
对象作为其参数 。 您在上面的代码中传递的内容只是GeneratorFunction
saga / Generator对象的GeneratorFunction。 有关生成器及其工作原理的详细介绍,请查看本文 。 你在takeEvery
之前使用yield*
并使用takeLatest
生成器。 使用yield*
将扩展整个序列 。 所以你可以这样想:它填补了这条线
yield* takeEvery([START, TICK], timerTickWorkerSaga)
同
while (true) { const action = yield take([START, TICK]) yield fork(timeTickWorkerSaga, action) }
而且我认为这不是你想要的,因为我相信这最终会阻止你的timerTickSaga
的第二行。 相反,你可能想要:
yield fork(takeEvery, [START, TICK], timerTickWorkerSaga)
这会取消takeEvery
效果,因此不会阻止下一行。
你传递给takeLatest
的第二个参数只是一个对象 - 一个CANCEL效果对象 。 takeLatest
的第二个参数实际上应该是一个GeneratorFunction
,它将在匹配STOP
模式的动作被调度到Redux存储时运行。 所以这应该是一个传奇功能。 您希望这取消fork(takeEvery, [START, TICK], timerTickWorkerSaga)
任务,以便将来的START
和TICK
操作不会导致timerTickWorkerSaga
运行。 你可以通过使用由fork(takeEvery...
产生的Task
对象运行一个CANCEL
效果来实现这一点fork(takeEvery...
效果。我们可以将Task
对象作为takeLatest
传奇的附加参数 。所以我们最终会得到一些东西。线条:
export default function * timerTickSaga () { const workerTask = yield fork(takeEvery, [START, TICK], timerTickWorkerSaga) yield fork(takeLatest, STOP, cancelWorkerSaga, workerTask) } function* cancelWorkerSaga (task) { yield cancel(task) }
有关其他参考,请查看redux-saga文档中的任务取消示例 。 如果你查看那里的main
传奇,你会看到fork
效果如何产生一个Task
对象/描述符,在产生cancel
效果时会进一步使用它。
rayd的答案是非常正确的,但在takeEvery和takeLatest内部正在做分叉的方式有点多余。 你可以在这里看到解释:
所以代码应该是:
export default function* timerTickSaga() {
const workerTask = yield takeEvery([START, TICK], timerTickWorkerSaga);
yield takeLatest(STOP, cancelWorkerSaga, workerTask);
}
function* cancelWorkerSaga(task) {
yield cancel(task);
}
Redux-Saga现在有一种方法,它叫做种族race
。 它将运行2个任务,但是当一个任务完成时,它将自动取消另一个任务。
watchStartTickBackgroundSaga一直在运行
export function* watchStartTickBackgroundSaga() {
yield takeEvery([START, TICK], function* (...args) {
yield race({
task: call(timerTickWorkerSaga, ...args),
cancel: take(STOP)
})
})
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.