【问题标题】:RxJs polling, error handling, retryWhen & retryCount resettingRxJs 轮询、错误处理、retryWhen & retryCount 重置
【发布时间】:2023-03-29 05:50:02
【问题描述】:

我正在尝试实施如下所示的轮询策略:

  • 每 X 秒从服务器请求数据
  • 如果请求失败,显示错误消息:“错误接收数据,重试尝试N°”... 每 X 秒重试一次,最多重试 Y 次
  • 如果重试次数 > Y 则显示错误消息“接收数据时出错,请稍后重试”

目前的代码如下:

  polling$ = combineLatest([timer(0, 1000), this._filters]).pipe(
exhaustMap((_) =>
  this.noteDataService.getAll().pipe(
    retryWhen((error$) =>
      error$.pipe(
        map((err, i) => ({ err, i })),
        tap(({ i }) =>
          console.log(`Error receiving data, retry attempt ${i + 1}`)
        ),
        // retry every X seconds for a maximum of Y times
        take(5),
        delay(1000),
        tap({
          complete: () =>
            console.log("Error receiving data, please try again later"),
        })
      )
    )
  )
)

);

问题是在 X 次尝试后它不会停止并再次尝试 X 次......等等。我想我与 combineLatest 运算符中的第一个计时器有关,但我没有看到解决方案,我尝试插入“第一个”运算符,但在第一次失败后轮询不会重新尝试 X 次。

【问题讨论】:

  • combineLatest 这里的目的是什么?
  • 我使用combineLatest过滤数据,可以调用_filters.next()获取查询参数过滤的数据

标签: angular rxjs polling


【解决方案1】:

使用局部变量来保持重试次数是完全可以的。此外,您想在此处使用concat,以确保发射不会并行发生:

  startPolling(interval = 1000, retry = 10): Observable<Response> {
    let retryCount = 0;

    // pull the data every "interval" seconds
    return timer(0, interval).pipe(
      switchMap((_) => this.requestData()),
      tap((res) => {
        if (!res.ok) {
          // if response is failed, throw error, so "retryWhen" will be triggered
          throw res;
        } else {
          // if response is success, reset retryCount
          retryCount = 0;
        }
      }),
      retryWhen((res) => {
        return res.pipe(
          // use "concatMap" to ensure that data emitting will be happening in order
          concatMap((data) => {
            // if we exceed retry count, then just interrupt "retryWhen" loop
            if (retryCount >= retry) {
              console.log('Error receiving data, please try again later');
              return throwError(EMPTY);
            }

            // increment retry count and run next delay next retry
            retryCount += 1;
            console.log(`Error receiving data. Retry number ${retryCount}`);
            return of(data).pipe(delay(interval));
          }),
        );
      }),
    );
  }

【讨论】:

    【解决方案2】:

    这是我将如何执行此操作的示例。大多数情况下,您可以使用 RxJS 运算符为您管理状态,无需创建自己的局部变量。

    const requestData = () => timer(2000).pipe(
      tap(_ => {throw "This is an error";})
    );
    
    // Request data from server every X seconds
    const requestInterval = 1000;
    interval(requestInterval).pipe(
      exhaustMap(_ => requestData().pipe(
        retryWhen(error$ => error$.pipe(
          map((err,i) => ({err,i})),
          tap(({i}) => console.log(`Error receiving data, retry attempt ${i + 1}`)),
          // retry every X seconds for a maximum of Y times
          take(5),
          delay(requestInterval),
          tap({
            complete: () => console.log("Error receiving data, please try again later")
          })
        ))
      ))
    ).subscribe();
    

    更新:

    如果您希望在收到太多连续错误后轮询间隔出错,而不是完成您的 retryWhen observable,您可以发出错误。

    const requestData = () => timer(2000).pipe(
      tap(_ => {throw "This is an error";})
    );
    
    // Request data from server every X seconds
    const requestInterval = 1000;
    interval(requestInterval).pipe(
      exhaustMap(_ => requestData().pipe(
        retryWhen(error$ => error$.pipe(
          map((err,i) => ({err,i})),
          tap(({i}) => console.log(`Error receiving data, retry attempt ${i + 1}`)),
          // retry every X seconds for a maximum of Y times
          take(5),
          delay(requestInterval),
          concatWith(throwError(() => "Error receiving data, please try again later"))
        ))
      ))
    ).subscribe({error: e => console.log("Printing the error: ", e)});
    

    【讨论】:

    • 您好,感谢您的回复,当我在 X 次尝试后使用您的方法时,我仍然遇到问题,它不会停止并重试其他 X 次尝试......等等。我更新了原始帖子中的代码
    • 我以为这就是你所追求的……即便如此,这也很容易解决。只需将retryWhen 的来源从requestData 更改为interval
    • @user7616817 - 我的答案已包含更新
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    相关资源
    最近更新 更多