将redux-saga与setInterval一起使用 - 如何以及何时产生

dou*_*ald 8 generator redux-saga

刚刚从thunk转移到sagas我正试图找到最好的方法来调用setTimeout,然后从该函数内调用另一个函数(在这种情况下corewar.step()).这是我原来的代码,正如我所料.

  runner = window.setInterval(() => {

    for(let i = 0; i < processRate; i++) {
      corewar.step()
    }

    operations += processRate;

  }, 1000/60)
Run Code Online (Sandbox Code Playgroud)

这段代码在a里面saga,我相信我应该可以call像在应用程序的其他区域中那样包装函数调用.

我已经尝试将setInterval调用包装在一个call并保留其他所有内容,这导致step()永远不会被调用.

  runner = yield call(window.setInterval, () => {

    for(let i = 0; i < processRate; i++) {
      corewar.step()
    }

    operations += processRate;

  }, 1000/60)
Run Code Online (Sandbox Code Playgroud)

我已经尝试过,保持setInterval原样并将step()函数包装在一个调用中并更改匿名函数签名,function*这也导致step()永远不会被调用.

  runner = window.setInterval(function*() {

    for(let i = 0; i < processRate; i++) {
      yield call([corewar, corewar.step])
    }

    operations += processRate;

  }, 1000/60)
Run Code Online (Sandbox Code Playgroud)

最后,我尝试包装两者,这再次导致step()永远不会被调用.

  runner = yield call(window.setInterval, function*() {

    for(let i = 0; i < processRate; i++) {
      yield call([corewar, corewar.step])
    }

    operations += processRate;

  }, 1000/60)
Run Code Online (Sandbox Code Playgroud)

感觉就像我在这里遗漏了一些东西所以我的问题是,我是否应该完全包装这些功能call或者这是错的?

接下来的问题是,我是否应该将外部包装setInterval在一个call将是我应该如何定义一个函数作为一个参数call,也想要产生一个putcall自己?

mad*_*adc 11

saga-redux文档中有一节名为" 使用eventChannel工厂连接外部事件 ",建议使用channels.

本节还提供了一个setInterval实现示例:

import { eventChannel, END } from 'redux-saga'

function countdown(secs) {
  return eventChannel(emitter => {
      const iv = setInterval(() => {
        secs -= 1
        if (secs > 0) {
          emitter(secs)
        } else {
          // this causes the channel to close
          emitter(END)
        }
      }, 1000);
      // The subscriber must return an unsubscribe function
      return () => {
        clearInterval(iv)
      }
    }
  )
}
Run Code Online (Sandbox Code Playgroud)

然后yield call,您将使用和yield takeEvery设置它:

const channel = yield call(countdown, 10);
yield takeEvery(channel, function* (secs) {
    // Do your magic..
});
Run Code Online (Sandbox Code Playgroud)


Kra*_*mir 6

const anotherSaga = function * () {
  const runner = yield call(setInterval, () => {
    console.log('yes');
  }, 1000);
  console.log(runner);
}
Run Code Online (Sandbox Code Playgroud)

这对我来说很好。在第二个片段)的末尾有一个双精度字,应该只有一个。


Gen*_*Jam 5

虽然有点晚了,但这是在传奇中设置计时器问题的最佳搜索结果。由于传奇的性质,有一个替代解决方案。从这里。

我这样调整:

function* callSelfOnTimer({ value }) {
  // Do your work here
  ...
  // If still true call yourself in 2 seconds
  if (value) {
    yield delay(2000);
    yield call(callSelfOnTimer, { value });
  }
}
Run Code Online (Sandbox Code Playgroud)