angularhttprxjs

RxJS add catch() to an Observable that's been shared


I have the following code I'm using in my Angular (4.0) application during $http calls.

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'));

After testing this I realized multiple subscriptions were triggering the request multiple times. Thanks to this post: Angular2 http.post gets executed twice I found out I needed to share() the result.

This works to get rid of the multiple calls but now it seems my catch() method isn't being hit. I want my catch() to throw the error.

I tried the two options below but they did not work:

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

Anyone know how I can share() and catch(throw...) at the same time?


Solution

  • The second option you've included in your question attaches the catch to the Observable.throw. If that is corrected, you should see the behaviour you are expecting:

    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>