3

我正在尝试通过重试来实现 Angular5 http.get。我写

http.get<any>('/api/study').retryWhen(
    (errors: Observable<any>):Observable<any> => {
        return errors.flatMap((error: any) => {
            if (error.status  == 500) {
                return Observable.of(error.status).delay(1000);
            }
            return Observable.throw(error);
        }).take(5);
    });

如果收到错误 500,这将继续重试 5 次。但是,如果它连续 5 次失败,则返回成功(带有空数据)。我不想要那个。相反,我希望它抛出最后一个错误。

我试图放在.concat(Observable.throw({}))take() 之后,这很有效,但它没有给我任何信息,例如最近错误的状态代码。

上次重试失败后如何获取最近的错误?

4

2 回答 2

3

您不需要使用take(5)来计算失败的尝试并使用局部变量自己计算。

例如,您可以这样做:

http.get<any>('/api/study').retryWhen((errors: Observable<any>) => {
    let errors = 0;

    return errors.flatMap((error: any) => {
        if (errors++ < 5 && error.status  == 500) {
            return Observable.of(error.status).delay(1000);
        }
        return Observable.throw(error);
    });
});
于 2018-02-27T16:39:46.460 回答
3

.retryWhen只能完成或出错- 在这两种情况下,都会中止进一步的重试。请参阅文档

因此,当您添加时,.take(5)您基本上是在告诉它重试 5 次然后完成,此时它只能完成(因此也不能返回错误 - 它是一个或另一个,而不是两者)。

所以使用.take()不会解决你的问题。

不幸的是,这意味着您必须在 retryWhen 中自己跟踪重试计数 - 所以对于 5 次计数,您只需让它返回错误(这将触发重试),最后在计数 6 时您手动抛出错误。然后,您可以在 catch 块中捕获最终错误。

像这样的东西(代码未经测试,但显示了这个想法):

http.get<any>('/api/study').retryWhen(err => {
    console.log('retrying');
    let retries = 0;
    return err
      .delay(1000)
      .map(error => {
        if (retries++ === 6) {
          console.log('retry number ', retries);
          throw error; <- THIS WILL CAUSE retryWhen to complete
        }
        return error; 
      });
  })
  .catch(err => {
    console.log('caught');
    return Observable.of(err);
  })
  .subscribe(data => {
    console.log('subscriber');
    console.log(data);
  });

作为旁注,添加 .concat(Observable.throw({})) 并不能解决您的问题,因为当它触发时,您的 5 次重试已完成,因此 retryWhen 已完成(即返回完成,因此没有错误) . 这就是 concat 无法抛出最后一个错误的原因,因为它从未收到它。

于 2018-02-27T17:03:13.677 回答