4

I have a Subject (this.searchSubject) which I call next() on when I want to perform a search:

this.searchSubject.next(postBody)

This causes the following to fire:

this.searchSubject
      .switchMap((view: any) => {
         // upsert here records the search - needed
         return this.searchHistoryService.upsert(view)
          .flatMap(() => this.http.post(this.url, view))
          .map((data) => this.pageTransform(data));
      })
      .subscribe(res => {
        this.successSubject.next(this.pageTransform(res));
      }, err => {
        this.errorSub.next(err);
      });

Unfortunately, no matter what I do, I can't seem to keep the stream alive if this.errorSub.next(err); is called (the error condition).

Since the httpClient (this.http.post) returns a new observable each I wouldnt have thought handling the error would be an issue, but it seems this removes all observers from this.searchSubject.

Note I have a httpInterceptor which returns a thrown error for every error returned.

This must be an extremely common pattern, so what am I doing wrong?

2
  • Which rxjs version are you using? Commented Apr 11, 2018 at 15:42
  • upwards of 5.5.2 Commented Apr 11, 2018 at 15:44

1 Answer 1

4

Your error handler is in the outer switchMap projection, thus it will close the outer stream in case of an error. You'll have to move it inside to your switchMap to keep the outer stream alive.

And since you're using [email protected] you can use the lettable operators which might make it easier to see where to put your error handlers.

this.searchSubject.pipe(
  switchMap((view: any) => {
   return this.searchHistoryService.upsert(view)
    .pipe(
      flatMap(() => this.http.post(this.url, view)),
      map((data) => this.pageTransform(data)),
      catchError(() => {
        this.errorSub.next(err); 
      })
    );
  })
).subscribe(() => {
  this.successSubject.next(this.pageTransform(res));
});

An important note if you switch to the lettable operators is that you have to import them from rxjs/operators like import { map, catchError } from 'rxjs/operators'; .

If you stay with the old syntax I think it will be as easy as to add a .catch after your .map() projection.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for this, I figured out that the outer observable was being closed as you said, its just a case now of trying to get my solution like yours, although i hadnt seen catchError, will that mean no error will be raised to searchSubject?
The catchError is just a rename of the old catch since the latter is a reserved keyword. Exactly, you'll have to handle the error inside.
You have to return something to catchError, so I return an Observable.of(err), which calls the success method in the subscription. Any idea how to avoid returning this?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.