【问题标题】:How to use retryWhen with a function that returns a Boolean?如何将 retryWhen 与返回布尔值的函数一起使用?
【发布时间】:2017-03-04 05:30:04
【问题描述】:

这是我的代码:

this._http.post(this._url_get + extension, '', { headers: headers })
    .map(res => res['_body'])
    .retryWhen(errors => {return responseErrorProcess(errors)})

现在我需要捕获异常并将它们传递给我的responseErrorProcess(),如果需要重试,它会返回true

我不知道如何从errors 中检索异常,这就是它的外观:

Subject_isScalar: falseclosed: falsehasError: falseisStopped: falseobservers: Array[0]thrownError: null__proto__: Observable`

它似乎不包含有关发生的异常的错误,而且我不知道应该返回什么才能实际重试。

【问题讨论】:

    标签: angular rxjs rxjs5 angular2-observables


    【解决方案1】:

    retryWhen() 的可调用对象需要返回一个 Observable,该 Observable 发出 completeerror 以结束流或发出一个值以重新订阅。

    例如,由于Observable.empty(),此代码完成而没有发出错误:

    Observable.create(obs => {
        obs.next(1);
        obs.next(2);
        obs.error('error from source');
      })
      .retryWhen((errors) => {
          errors.subscribe(sourceError => console.log(sourceError));
          return Observable.create(obs => obs.error('inner error'));
      })
      .subscribe(
        val => console.log(val),
        err => console.log('error', err),
        _ => console.log('complete')
      );
    

    源 Observable 的错误以next 的形式发送到errors。见源码:https://github.com/ReactiveX/rxjs/blob/master/src/operator/retryWhen.ts#L86

    这会打印到控制台:

    1
    2
    error inner error
    error from source
    

    观看现场演示:http://plnkr.co/edit/Fajsb54WJwB8J8hkUC6j?p=preview

    根据下面的 cmets 进行编辑:

    查看retryWhen()的文档:

    一个错误将导致 Throwable 的发射,导致 notificationHandler 返回的 Observable 发生错误。如果该 Observable 调用 onComplete 或错误,那么 retry 将在子订阅上调用 complete 或 error。 否则,此 Observable 将重新订阅特定调度程序上的源 observable

    所以回调返回的 Observable 负责决定是否重新订阅。如果它发出next(),则重新订阅。如果它发出 error()complete() 将它们传递给子 Observer。

    例如你可以这样做(我没有测试这段代码):

    return response.retryWhen((errors) => {
        var retrySource = new Subject();
        errors.subscribe(error => {
            if (this.responseErrorProcess(error)) retrySource.next();
            else retrySource.complete();
        });
        return retrySource;
    });
    

    根据您的内在逻辑,您在retrySource 上触发了正确的消息。

    【讨论】:

    • 谢谢!但如何得到错误?你看,我们得到这样的错误是一个可观察的并且实际上不包含异常,与我使用 .catch() 得到的错误不同,它实际上包含 http 响应(对不起,我的解释方式很弱)
    • @MotassemMK 查看我的更新答案。它的工作原理与reactivex.io/rxjs/class/es6/… 中记录的完全相同。然而,我同意这个描述经常是非常令人困惑的。
    • 很好,我得到了错误!但是,(很抱歉,这是第二个后续问题)我怎样才能从 flatMap 内部将一个值返回给 retryWhen 作为它的异步?这是我尝试过的:
    • @MotassemMK 我更新了我的答案,看看底部。
    • @MotassemMK 你是对的,使用subscribe() 而不是flatMap
    【解决方案2】:

    retryWhen 应该返回一个 Observable。一旦该 observable 发出,就会发生重试:

    .retryWhen(errors => 
        //switchMap to retrieve the source error
        errors.switchMap(sourceErr => 
            //send source to processor
            responseErrorsProcess(sourceErr) ? 
            //if result is TRUE, emit (will cause retry). Else, pass on the error
            Observable.of(true): Observable.throw(sourceErr)
        )
    )
    

    如果您想在处理器返回 false 时完成而不是出错,请将 Observable.throw() 替换为 Observable.empty()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-05
      • 1970-01-01
      • 2021-10-29
      • 2013-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多