Subject in Angular stops working after 500 internal error

Viewed 673

I have a pub/sub pattern used to send data changes from a menu item, to a Leaflet component in my Angular application, however, when the server returns an internal server error(code:500), the pub/sub stops working, meaning any additional clicks don't fire the subscription on the other end.

I've been unable to trace why this is happening, and forcing the users to refresh the page after an internal server error(code:500) is not really the point of an SPA.

code example

  setAccountID(event: MouseEvent, node: IAccount) {
    this.stopPropogation(event);
    this.accountChangeService.accountID = node.id;
    this.accountChangeService.setAccountID();
  }

The snippet above, is used in the menu tree to change the account the user's trying to view. Each administrative user will be able to swap between accounts they manage.

The accountChangeService looks like this:

@Injectable({
  providedIn: 'root'
})
export class AccountChangeService {

  accountID: string;
  accountIDChange: Subject<string> = new Subject<string>();

  constructor() {
    this.accountIDChange.subscribe((value) => {
      this.accountID = value;
    });
  }

  setAccountID() {
    this.accountIDChange.next(this.accountID);
  }
}

I then use this service again, subscribe to the change, and use the value to pull information from a service:

this.accountChangeService.accountIDChange
  .pipe(tap(output => {
    /** code left out for brevity **/
    return output; 
  }),
  switchMap((output: any) => this.service.retrieveAccountInformation({ 
    id: output 
  })))
  .subscribe(output => {
    /** code left out for brevity **/
});

The issue arise, when an error is throw with in the switchMap(...) statement, the entire call blocks, so no subsequent calls go through.

I have tried added catchError, error in the subscribe, even an Exception handler globally to figure out why it won't allow any calls after the internal 500.

I need to capture the 500 internal, show the user an error, and allow them to try a different call.

Can't figure out what I'm doing wrong?

3 Answers

This all comes down where you put the catchError. Once an RxJS chain receives an error it automatically unsubscribes so you want to use catchError inside switchMap like the following:

switchMap(output => this.service.retrieveAccountInformation({ 
    id: output 
  }).pipe(
    tap({ error: /* show error message */ }),
    catchError(() => EMPTY), // ignore the error and emit nothing
  )
),

You can of course turn the error into next a regular notification if you need to.

try like this:

.pipe(
  switchMap((output: any) => this.service.retrieveAccountInformation({ 
    id: output 
  })),
  catchError(e => { /* your logic */})
)

this is Observable Contract that whenever it encounter error it will stop working. I think u have to catch error before going in to observable and map error other acceptable state.

this.accountChangeService.accountIDChange
  .pipe(tap(output => {
    /** code left out for brevity **/
    return output; 
  }),

  switchMap((output: any) => this.service.retrieveAccountInformation({ 
    id: output 
  }))).pipe(CatchError(error=> {
// show error to user
 return of(null)
}))

  .subscribe(output => {
    /** code left out for brevity **/
});

try this

For more information please read this blog

Related