当启动操作被分派时,我启动秒表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)
}以及第一个代码块中的方法,我试图从监视服务中停止这个传奇。
发布于 2016-06-08 13:07:17
看起来这里发生了一些事情:
cancel side effect takes a Task object as its argument.在上面的代码中传递给它的只是创建saga/生成器对象的GeneratorFunction。有关生成器及其工作原理的详细介绍,请查看在使用yield*之前使用takeEvery和takeLatest生成器的this article.yield*将执行spread the whole sequence。所以你可以这样想:它填充了这行yield* takeEvery([START, TICK], timerTickWorkerSaga)
使用
while (true) { const action =START(START,TICK) START(timeTickWorkerSaga,action) }
我不认为这是你想要的,因为我相信这最终会阻塞你的timerTickSaga的第二行。相反,您可能希望:
收益分叉(takeEvery,START,TICK,timerTickWorkerSaga)
这将派生出takeEvery效果,因此它不会阻塞下一行。
takeLatest的第二个参数只是一个对象--一个CANCEL effect object。takeLatest的第二个参数实际上应该是一个GeneratorFunction,它将在与STOP模式匹配的操作被分派到Redux存储时运行。所以这真的应该是一个传奇函数。您希望这会取消fork(takeEvery, [START, TICK], timerTickWorkerSaga)任务,以便将来的START和TICK操作不会导致timerTickWorkerSaga运行。您可以通过让saga对由fork(takeEvery...效果产生的Task对象运行CANCEL效果来实现这一点。我们可以将Task对象作为takeLatest传奇的additional argument。所以我们最终得到了一些类似的东西:export default function* timerTickSaga () { const workerTask = yield (takeEvery,START,TICK,timerTickWorkerSaga) yield (takeLatest,STOP,cancelWorkerSaga,workerTask) } function * cancelWorkerSaga (task) { yield cancel(task) }
要获得更多参考,请查看redux-saga文档中的task cancellation example。如果你看看main传奇,你会看到fork效应是如何产生一个Task对象/描述符的,当产生cancel效应时,这个对象/描述符会被进一步使用。
发布于 2017-08-22 06:06:11
Redux-Saga现在有一个解决这个问题的方法,叫做race race。它将运行两个任务,但当其中一个任务完成时,它将自动取消另一个任务。
”和"cancel“并不重要,它们只有助于代码的可读性
export function* watchStartTickBackgroundSaga() {
yield takeEvery([START, TICK], function* (...args) {
yield race({
task: call(timerTickWorkerSaga, ...args),
cancel: take(STOP)
})
})
}发布于 2016-10-31 00:52:34
rayd的答案是非常正确的,但在takeEvery和takeLatest内部做分支的方式上有点多余。您可以查看here的说明
所以代码应该是:
export default function* timerTickSaga() {
const workerTask = yield takeEvery([START, TICK], timerTickWorkerSaga);
yield takeLatest(STOP, cancelWorkerSaga, workerTask);
}
function* cancelWorkerSaga(task) {
yield cancel(task);
}https://stackoverflow.com/questions/37689562
复制相似问题