使用Angular http.get重试失败后抛出错误

时间:2018-02-27 16:20:41

标签: angular reactjs rxjs retrywhen

我正在尝试使用重试来实现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()之后,这样可行,但它没有给我任何信息,例如最近错误的状态代码。

如何在上次重试失败后获取最新错误?

2 个答案:

答案 0 :(得分: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);
    });
});

答案 1 :(得分:1)

.retryWhen只能完成或错误 - 在这两种情况下,都会中止进一步的重试。 See docs

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

因此使用.take()无法解决您的问题。

不幸的是,这意味着您必须在重试时自己跟踪重试次数 - 所以对于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次重试已完成,因此重试时已完成(即返回完成) ,所以没有错误)。这就是concat无法抛出最后一个错误的原因,因为它从未收到它。