另一个rxjs Observable重试策略

时间:2017-07-11 21:07:46

标签: angular rxjs

我已经看过十几种实施重试策略的方法,我觉得我真的非常接近。在takeWhile()完成后,我所拥有的内容并不会引发错误。

getItems(): Observable<ListItem[]> {
    return this.authHttp.get(URL + '/items')
      .retryWhen(e => 
        e.scan((errorCount, err) => errorCount + 1, 0)
          .takeWhile(errorCount => errorCount < 4)
          .delay(3000))
      .map(this.dataService.extractData)
      .catch(err =>  this.dataService.handleError(err, 'The items could not be retrieved.'))
  }

我已经看到了一些看似锯齿状的代码片段,可能会让它完成。我尝试在.finally()之前插入.delay()

一旦我解决了这个问题,我就想将errorCount传递回我的订阅,以便我可以显示有用的内容。 &#34;重试1/4。&#34;让用户知道发生了什么的东西。

1 个答案:

答案 0 :(得分:3)

使用retryWhen,您可以使用传递给通知程序的observable做一些事情。你可以:

  • 发出收到的错误通知以重试;
  • 完成observable以放弃重试而不会出错;
  • 抛出错误以拒绝重试但错误。

在使用takeWhile时,您正在发送通知然后正在完成 - 它会看到重试停止而没有错误。

听起来您想要发出通知,但随后会抛出错误:

getItems(): Observable<ListItem[]> {
  return this.authHttp.get(URL + '/items')
    .retryWhen(e => e.scan((errorCount, error) => {
        if (errorCount >= 4) {
          throw error;
        }
        return errorCount + 1;
      }, 0)
      .delay(3000)
    )
    .map(this.dataService.extractData)
    .catch(err =>  this.dataService.handleError(err, 'The items could not be retrieved.'));
}

要将重试逻辑划分为可重复使用的函数,您可以使用let - “让我拥有整个可观察的” - 运算符:

import 'rxjs/add/operator/let';

function handleRetry<T>(source: Observable<T>): Observable<T> {
  return source.retryWhen(e => e.scan((errorCount, error) => {
      if (errorCount >= 4) {
        throw error;
      }
      return errorCount + 1;
    }, 0)
    .delay(3000)
  );
}

getItems(): Observable<ListItem[]> {
  return this.authHttp.get(URL + '/items')
    .let(handleRetry)
    .map(this.dataService.extractData)
    .catch(err =>  this.dataService.handleError(err, 'The items could not be retrieved.'));
}