我正在编写一个史诗,该史诗每隔一定的秒数轮询一次服务器,在这种情况下为3秒启动延迟,每5秒轮询一次,使用计时器通过管道传输对其进行计时,但是我不确定此行为背后的原因。
我的史诗片并不等待我的内心完成,因此输出确实很奇怪。
我尝试过更改地图并使用exhaustMap,但是不确定我是否在树右边。
export const testingEpics = action$ => {
// Stop upon a end pending action trigger, for debugging/stopping if needed
const stopPolling$ = action$.pipe(ofType(END_PENDING_ACTIONS));
return action$.pipe(
// On begin pending actions
ofType(BEGIN_PENDING_ACTIONS),
switchMap(action =>
// At a 5 second interval
timer(3 * 1000, 5 * 1000).pipe(
// Stop when epics see a end pending action
takeUntil(stopPolling$),
switchMap(() =>
// Get the db
from(getDb()).pipe(
mergeMap(db => {
console.log('Run again!!');
return from(
new Promise(resolve => setTimeout(resolve, 10000))
).pipe(
// what happens if action is still running but no internet?
// delay(9.9 * 1000),
// actions is an array from the db
// switchmap at top is reason for it, handle for future. lol
map(actions => console.log('Hello world'))
);
})
)
)
)
)
);
};
预期结果将是
(Initial delay 3 seconds)
Run Again!!
(Wait's 10 seconds for inner promise to complete)
Hello world
(Subsequent delay of 5 seconds)
Run Again!!
(Wait's another 10 seconds for inner promise to complete)
Hello world
(Subsequent delay of 5 seconds)
Run Again!!
(Wait's another 10 seconds for inner promise to complete)
Hello world
(Subsequent delay of 5 seconds)
.
.
.
答案 0 :(得分:0)
请尝试将所有switchMap
更改为concatMap
,如果您希望所有请求都通过并进行查询,exhaustMap
将跳过源可观察到的发射,直到内部发射完成,因此您可能会错过很多要求。另一方面,一旦父可观察对象发出,switchMap
将取消内部可观察对象,因此您的getDb()
承诺将被取消
答案 1 :(得分:0)
interval
和timer
可用于生成一个循环,该循环的执行频率不受实际轮询服务器所需时间的影响。根据您的“预期结果”描述,您好像想要的频率受实际轮询服务器所需时间长度的影响。我在考虑您的用例,例如以下(同步)循环:
delay(3) // synchronously wait 3 seconds
while (!stopped) {
pollServer() // synchronously poll server; may take N seconds
delay(10) // synchronously wait 10 seconds
}
我将使用repeatWhen
在史诗中构造以上循环。 repeatWhen
使得仅在“循环迭代”完成之后才可以轻松启动10秒延迟。您只需在可观察的通知内延迟完成事件即可:
export const epic = action$ =>
action$.pipe(
ofType(BEGIN_PENDING_ACTIONS),
exhaustMap(action => // ignore actions while the loop is already running
of(action).pipe( // re-pipe so we can attach `takeUntil` to stop running the loop
delay(3000), // this is the initial delay
mergeMap(() =>
from(getDb()).pipe( // this is the start of the loop iteration
mergeMap(db => ...), // this is where you poll the server and emit Redux actions
repeatWhen(complete$ =>
complete$.pipe(
delay(10000), // on complete, wait 10 seconds, then repeat!
)
),
)
),
takeUntil(action$.pipe( // stop on end
ofType(END_PENDING_ACTIONS)
)),
)
),
)
请注意,在上面的示例中,repeatWhen
将仅重新订阅from(getDb())
。 db
的值将始终是第一次迭代后的缓存值。如果您需要在每次迭代中重新执行getDb()
,请替换为defer(() => from(getDb()))
。