当我们开始轮询时,一切都会按预期进行。一旦我们停止并重新开始,$continueRefreshStudents 就会停止工作。 请检查 stackblitz 示例。
重现步骤:
https://stackblitz.com/edit/angular-ngrx-polling2?file=src%2Fapp%2Fstate%2Fapp.effects.ts
当您使用
takeWhile
时,一旦停止轮询将 isPollingActive
更改为 false,它就会完成效果中的可观察值。每次开始轮询时,ngrx 不会创建新效果,因此后续 getDataSuccess
操作效果不会发生。您可以将 takeWhile
更改为 filter
,这样当 isPollingActive
为 false 时,您就可以忽略效果。
但是我不确定这是最好的方法,该方法具有触发相同操作再次发生的效果。我觉得让开始操作创建一个
interval
可以触发继续操作,而停止操作停止 interval
会不会那么混乱。
您可以将
takeWhile
移动到内部可观察量(在 mergeMap
内)管道来解决此问题,因为在这种情况下,一旦 isPollingActive
发生更改,它将完成内部可观察量,而不是主效应的可观察量:
public continuePolling$ = createEffect(() =>
this.actions$.pipe(
ofType(appActions.getDataSuccess),
tap(data => console.log('app effect continue polling')),
takeWhile(() => this.isPollingActive),
delay(2000),
mergeMap(() =>
this.appDataSurvice.getData().pipe(
switchMap(data => {
return [appActions.getDataSuccess(data)];
}),
catchError(err => of(appActions.getDataFail(err))),
takeWhile(() => this.isPollingActive), // check again incase this has been unset since delay
)
)
)
);
谢谢@Hopey One,和OP一样,我用的是
takeWhile
,但我把它改成了使用filter
。
是的,您可以使用一种具有重试限制且无需计时器的效果来调用自身。
deliverMessages$ = createEffect(
() =>
this.actions$.pipe(
ofType(MessageActions.addMessage, MessageActions.addMessageSuccess, MessageActions.addMessageFailed),
withLatestFrom(this.store.select(selectMessages)),
filter(([_action, messages]) => {
return messages.length >= 1;
}),
switchMap(([_action, messages]) => {
const payload = messages[0];
return this.messagesService.addMessage(payload)).pipe(
map(() => {
// If Succeed, remove the message from the queue
return MessageActions.addMessageSuccess(payload)
}),
catchError(error => {
// If Failed, remove the message from the queue (after X retries).
return MessageActions.addMessageFailed({ error, payload })
})
);
}),
// Time span between messages
delay(5000),
),
);