Ngrx 轮询效果第二次停止工作

问题描述 投票:0回答:3

当我们开始轮询时,一切都会按预期进行。一旦我们停止并重新开始,$continueRefreshStudents 就会停止工作。 请检查 stackblitz 示例。

重现步骤:

  1. 开始轮询(检查控制台日志,轮询继续)
  2. 停止投票
  3. 开始第二次投票(这次投票不再继续)

https://stackblitz.com/edit/angular-ngrx-polling2?file=src%2Fapp%2Fstate%2Fapp.effects.ts

angular ngrx
3个回答
2
投票

当您使用

takeWhile
时,一旦停止轮询将
isPollingActive
更改为 false,它就会完成效果中的可观察值。每次开始轮询时,ngrx 不会创建新效果,因此后续
getDataSuccess
操作效果不会发生。您可以将
takeWhile
更改为
filter
,这样当
isPollingActive
为 false 时,您就可以忽略效果。

但是我不确定这是最好的方法,该方法具有触发相同操作再次发生的效果。我觉得让开始操作创建一个

interval
可以触发继续操作,而停止操作停止
interval
会不会那么混乱。


0
投票

您可以将

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

0
投票

谢谢@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),
      ),
  );
© www.soinside.com 2019 - 2024. All rights reserved.