刚刚从thunk转移到sagas我正试图找到调用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
完全包装这些功能或者这是错误的?
如果我应该将setInterval
包裹在call
中,那么我将如何定义一个函数作为call
的参数,这也是我想要产生的put
或call
本身?
答案 0 :(得分:8)
saga-redux文档中有一个名为“Using the eventChannel factory to connect to external events”的部分,建议使用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..
});
答案 1 :(得分:4)
const anotherSaga = function * () {
const runner = yield call(setInterval, () => {
console.log('yes');
}, 1000);
console.log(runner);
}
这对我来说非常好。在你的第二个片段中,最后只有一个)
,只有一个。
答案 2 :(得分:3)
这里的聚会晚了一点,但这是在传奇中设置计时器的最高搜索结果。由于sagas的性质,有一种替代解决方案。 From here.
我对此进行了修改:
function* callSelfOnTimer({ value }) {
// Do your work here
...
// If still true call yourself in 2 seconds
if (value) {
yield delay(2000);
yield call(callSelfOnTimer, { value });
}
}
答案 3 :(得分:1)
要使其正常工作,还需要添加以下内容:
const delay = (ms) => new Promise(res => setTimeout(res, ms))
function* callSelfOnTimer({ value }) {
// Do your work here
...
// If still true call yourself in 2 seconds
if (value) {
yield delay(2000);
yield call(callSelfOnTimer, { value });
}
}