Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

switchMap after catchError does not emit values

I'm using Angular and RxJS.

I intend to add an item to a collection (1st Observable), and then get the collection (2nd Observable), everything on the same stream of data.

Then I offer the Observable to the component and a child component receives it with an async pipeline.

The problem appears when first addItem AJAX call fails. I tried to keep returning the whole updated list of collection items, so child component has fresh data, but last step is never done and child item never receives the collection after an addItem fail.

This is my code:

public addItem(item) {

  this.itemCollection$ = this.itemService.addItem(item).pipe(
        catchError((err) => {
          this.logger.error('Couldnt add Item to Collection');
          return of();
        }),
        switchMap(() => 
  this.itemsService.getItemsByItemId(this.itemId)));

}

Console result:

POST http://localhost:3000/api/XXXX/XXX/XXXXX/items 400 (Bad Request)
ngx-logger.js:245 2019-05-29T17:25:39.557Z ERROR [items-page-module.9c3988b4c0f0dbc7bc65.hot-update.js:319] Couldnt add Item to Collection

So error is logged on console, but child component never gets the new list of items.

What should I do so itemCollection$ observable emits an item's collection, despite of the error?

Thank you!

like image 693
Alejandro Sanz Díaz Avatar asked Jan 01 '23 22:01

Alejandro Sanz Díaz


1 Answers

When you call of() it creates an observable that emits nothing but immediately completes, because it was given no arguments. The problem is that the switchMap() operator will only trigger in response to an emitted value.

Therefore, the following effectively silences all errors in an observable.

    throwError('ouch').pipe(
        catchError(() => of())
    ).subscribe(()=> {
         console.log('I am never printed');
    }, ()=> {
         console.log('I am never printed');
    }, ()=> {
         console.log('COMPLETED!'); // this will be printed.
    });

In the above example, the catchError() transitions to an empty observable. Neither the subscriber callback or error callback are executed. Only the complete callback is executed.

Any operators that exist after the catchError() are never used because nothing is emitted.

You can fix this by emitting undefined or any other value.

public addItem(item) {
    this.itemCollection$ = this.itemService.addItem(item).pipe(
        catchError((err) => {
          this.logger.error('Couldnt add Item to Collection');
          return of(undefined);
        }),
        switchMap(() => this.itemsService.getItemsByItemId(this.itemId)));
}
like image 180
Reactgular Avatar answered Jan 13 '23 09:01

Reactgular