首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当使用redux-saga调度操作时取消saga

当使用redux-saga调度操作时取消saga
EN

Stack Overflow用户
提问于 2016-06-08 05:20:17
回答 3查看 24K关注 0票数 21

当启动操作被分派时,我启动秒表React组件的计时器:

代码语言:javascript
复制
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操作时,我在停止传奇时遇到了麻烦。我试着在我的工人传奇中使用cancelcancelled效果:

代码语言:javascript
复制
if(yield(take(STOP)) {
  yield cancel(timerTickWorkerSaga)
}

以及第一个代码块中的方法,我试图从监视服务中停止这个传奇。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-06-08 13:07:17

看起来这里发生了一些事情:

  1. The cancel side effect takes a Task object as its argument.在上面的代码中传递给它的只是创建saga/生成器对象的GeneratorFunction。有关生成器及其工作原理的详细介绍,请查看在使用yield*之前使用takeEverytakeLatest生成器的this article.
  2. You're。使用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 objecttakeLatest的第二个参数实际上应该是一个GeneratorFunction,它将在与STOP模式匹配的操作被分派到Redux存储时运行。所以这真的应该是一个传奇函数。您希望这会取消fork(takeEvery, [START, TICK], timerTickWorkerSaga)任务,以便将来的STARTTICK操作不会导致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效应时,这个对象/描述符会被进一步使用。

票数 13
EN

Stack Overflow用户

发布于 2017-08-22 06:06:11

Redux-Saga现在有一个解决这个问题的方法,叫做race race。它将运行两个任务,但当其中一个任务完成时,它将自动取消另一个任务。

  • https://redux-saga.js.org/docs/advanced/RacingEffects.html
  • watchStartTickBackgroundSaga始终运行
  • 每当有开始或滴答,在timerTickWorkerSaga之间启动竞争并侦听下一个停止操作。
  • 当其中一个任务完成时,另一个任务被取消这是竞争的行为。
  • 竞争中的名称“

”和"cancel“并不重要,它们只有助于代码的可读性

代码语言:javascript
复制
export function* watchStartTickBackgroundSaga() {
  yield takeEvery([START, TICK], function* (...args) {
    yield race({
      task: call(timerTickWorkerSaga, ...args),
      cancel: take(STOP)
    })
  })
}
票数 13
EN

Stack Overflow用户

发布于 2016-10-31 00:52:34

rayd的答案是非常正确的,但在takeEvery和takeLatest内部做分支的方式上有点多余。您可以查看here的说明

所以代码应该是:

代码语言:javascript
复制
export default function* timerTickSaga() {
    const workerTask = yield takeEvery([START, TICK], timerTickWorkerSaga);
    yield takeLatest(STOP, cancelWorkerSaga, workerTask);
}

function* cancelWorkerSaga(task) {
    yield cancel(task);
}
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37689562

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档