【问题标题】:RxJS add catch() to an Observable that's been sharedRxJS 将 catch() 添加到已共享的 Observable
【发布时间】:2017-07-18 22:14:59
【问题描述】:

在 $http 调用期间,我在 Angular (4.0) 应用程序中使用了以下代码。

return this.httpComponent.post(serviceUrl, request, args)
            .map((res: any) => res.json() as R)
            .catch((error: any) => Observable.throw(error.json().error || error.json().errorMessage || 'Server error'));

经过测试,我意识到多个订阅会多次触发请求。感谢这篇文章:Angular2 http.post gets executed twice 我发现我需要share() 结果。

这可以摆脱多次调用,但现在我的 catch() 方法似乎没有被击中。我希望我的 catch() 能够抛出错误。

我尝试了以下两个选项,但它们都不起作用:

return this.httpComponent.post(serviceUrl, request, args)
    .map((res: any) => res.json() as R)
    .share()
    .catch((error: any) => Observable.throw(error.json().error || error.json().errorMessage || 'Server error'));

return this.httpComponent.post(serviceUrl, request, args)
    .map((res: any) => res.json() as R)
    .catch((error: any) => Observable.throw(error.json().error || error.json().errorMessage || 'Server error') 
    .share()); //This doesn't make sense since my catch() isn't returning an Observable

有谁知道我如何同时share()catch(throw...)

【问题讨论】:

    标签: angular http rxjs


    【解决方案1】:

    正如我对@cartant 回答的评论中提到的,如果任何订阅者没有错误处理程序(即:不关心任何错误场景),则会引发异常,并且所有后续订阅者都不会被告知原来的错误。

    在我看来,这似乎是一个设计缺陷。这是示例(从@cartant 的答案复制)

    const source = Rx.Observable
      .interval(500)
      .map((value) => {
        if (value === 2) {
          throw new Error("Boom!");
        }
        console.log(`value: ${value}`)
        return value;
      })
      .catch((error) => Rx.Observable.throw(new Error(`Re-thrown ${error.message}`)))
      .share();
    
    source.subscribe(
      (value) => console.log(`subscription 1: ${value}`)
    );
    source.subscribe(
      (value) => console.log(`subscription 2: ${value}`),
      (error) => console.log(`subscription 2: ${error}`)
    );
    .as-console-wrapper { max-height: 100% !important; top: 0; }
    <script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>

    【讨论】:

    • 仅供参考,似乎有一个未解决的问题:github.com/ReactiveX/rxjs/issues/2180 - 所以你不是唯一一个认为这是一个缺陷的人。
    • 感谢您的链接。我绝对认为应该改变这种行为。
    【解决方案2】:

    您在问题中包含的第二个选项将catch 附加到Observable.throw。如果该问题得到纠正,您应该会看到预期的行为:

    const source = Rx.Observable
      .interval(500)
      .map((value) => {
        if (value === 2) {
          throw new Error("Boom!");
        }
        console.log(`value: ${value}`)
        return value;
      })
      .catch((error) => Rx.Observable.throw(new Error(`Re-thrown ${error.message}`)))
      .share();
    
    source.subscribe(
      (value) => console.log(`subscription 1: ${value}`),
      (error) => console.log(`subscription 1: ${error}`)
    );
    source.subscribe(
      (value) => console.log(`subscription 2: ${value}`),
      (error) => console.log(`subscription 2: ${error}`)
    );
    .as-console-wrapper { max-height: 100% !important; top: 0; }
    <script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>

    【讨论】:

    • 我的例子中的代码实际上是一个错字。我没有尝试将 share() 附加到 throw()。但是您的代码 sn-p 帮助我找出了问题,所以我接受了您的回答。至于我的问题,原来最早的订阅者之一没有错误处理程序。因此,这似乎是 imo 的设计缺陷,所有后续订阅者都不会收到错误。
    猜你喜欢
    • 2018-02-01
    • 2020-03-04
    • 2021-08-24
    • 2018-07-18
    • 2015-08-14
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 2017-01-04
    相关资源
    最近更新 更多