当 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
动作时,我无法停止 saga。我尝试使用 cancel
和 cancelled
我的工人传奇中的效果:
if(yield(take(STOP)) {
yield cancel(timerTickWorkerSaga)
}
以及第一个代码块中的方法,我尝试从观看服务中停止传奇。
原文由 vamsiampolu 发布,翻译遵循 CC BY-SA 4.0 许可协议
看起来这里发生了一些事情:
cancel
副作用 采用Task
对象作为其参数。您在上面的代码中传递给它的只是创建 saga/Generator 对象的GeneratorFunction
。有关生成器及其工作原理的精彩介绍,请查看 这篇文章。yield*
在takeEvery
和takeLatest
生成器之前。使用yield*
将 传播整个序列。所以你可以这样想:它正在填充这条线yield* takeEvery([START, TICK], timerTickWorkerSaga)
和
而且我认为这不是您想要的,因为我相信这最终会阻塞您的
timerTickSaga
的第二行。相反,您可能想要:这分叉了
takeEvery
效果,因此它不会阻塞下一行。takeLatest
的第二个参数只是一个对象 - 一个 CANCEL 效果对象。takeLatest
的第二个参数实际上应该是GeneratorFunction
,当匹配STOP
模式的动作被调度到 Redux 存储时,它将运行。所以这真的应该是一个传奇功能。 You want this to cancel thefork(takeEvery, [START, TICK], timerTickWorkerSaga)
task so that futureSTART
andTICK
actions will not cause thetimerTickWorkerSaga
to run.您可以通过让 saga 运行CANCEL
效果和Task
效果来实现此目的fork(takeEvery...
效果。我们可以将Task
对象作为takeLatest
传奇的 附加参数。所以我们最终得到了以下内容:如需更多参考,请查看 redux-saga 文档中的 任务取消示例。如果
cancel
查看那里的main
传奇,您将看到fork
效果如何产生Task
进一步使用对象/描述符时产生的效果---
效果。