web-dev-qa-db-ja.com

setIntervalでredux-sagaを使用する-どのように、いつ生成するか

サンクからサガに移動したばかりで、setTimeoutを呼び出して、その関数内から別の関数(この場合はcorewar.step())を呼び出す最善の方法を見つけようとしています。これは私が期待したとおりに機能する私のオリジナルのコードでした。

_  runner = window.setInterval(() => {

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

    operations += processRate;

  }, 1000/60)
_

このコードはsaga内にあり、アプリケーションの他の領域で行ったように、call内で関数呼び出しをラップできるはずです。

私はsetInterval呼び出しをcallでラップし、それ以外のすべてをそのままにしてみました。その結果、step()が呼び出されなくなりました。

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

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

    operations += processRate;

  }, 1000/60)
_

setIntervalをそのままにして、step()関数を呼び出しでラップし、匿名関数のシグネチャを_function*_に変更して、step()呼び出されることはありません。

_  runner = window.setInterval(function*() {

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

    operations += processRate;

  }, 1000/60)
_

最後に、両方をラップしてみましたが、この場合もstep()が呼び出されることはありません。

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

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

    operations += processRate;

  }, 1000/60)
_

私はここで何か不足しているように感じるので、私の質問は、これらの関数をcallでラップする必要があるのか​​、それとも間違っているのですか?

私が外側のsetIntervalcallでラップすることになっている場合、次の質問は、関数をcallのパラメータとしてどのように定義する必要があるかを示します。 putまたはcall自体ですか?

9
dougajmcdonald
const anotherSaga = function * () {
  const runner = yield call(setInterval, () => {
    console.log('yes');
  }, 1000);
  console.log(runner);
}

これは私にはかなりうまくいきます。 2番目のスニペットには、二重)最後に1つだけでなければなりません。

6
Krasimir

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)
      }
    }
  )
}

次に、yield callおよびyield takeEveryを使用して設定します。

const channel = yield call(countdown, 10);
yield takeEvery(channel, function* (secs) {
    // Do your magic..
});
11
madc