matt
matt

Reputation: 749

RxJS - Using an observable in catchError block

I have 2 services budgetTestService and budgetService, I need to use budgetTestService when there's an error and budgetService when there's no error. The map() in the pipe of budgetTestService.getBudgetService() is not being called - console.log('test service complete');

Not sure if this how it should be done it kind of seems like I'm nesting and doing it wrong, am I using the syntax correctly?

this.budgetService.getBudgetDays(this.startDate, this.finishDate)
    .pipe(
      map(res => {
        console.log('get budget day server mapping');
        self.timelineBudgetDates = self.processDates(res);

      }),
      //map(res => {
      //  self.timelineBudgetDates = self.budgetTestService.getBudgetDates(self.startDate, self.finishDate);
      //})
      catchError(error => {
        console.log('error code running');
        console.log(error);
        self.budgetTestService.getBudgetDates(self.startDate, self.finishDate)
                              .pipe(
                                map(res => {
                                  console.log('test service complete');
                                  console.log(res);
                                  self.timelineBudgetDates = res;
                                })
                              );
        return of('some return value, maybe null, maybe a good default');
      })
    )

    .subscribe(res => {
      console.log('Response = ', res);
      //self.timelineBudgetDates = self.processDates(res);
      //self.timelineBudgetDates = res;

    });

The budgetTestService:

getBudgetDates(startDate: string, endDate: string): Observable<BudgetDate[]> {

    console.log('getting budget dates from test service');

    let dates = this.datesOfRange(moment(startDate), moment(endDate));
    //console.log('dates:', dates);

    let budgetDates: BudgetDate[] = [
      new BudgetDate({ moment: moment().subtract(1, 'd').startOf('d'), earned: 100, spent: 50, onServer: true }),
      new BudgetDate({ moment: moment().subtract(2, 'd').startOf('d'), earned: 101, spent: 51, onServer: true }),
      new BudgetDate({ moment: moment().subtract(3, 'd').startOf('d'), earned: 102, spent: 52, onServer: true }),
      new BudgetDate({ moment: moment().subtract(4, 'd').startOf('d'), earned: 103, spent: 53, onServer: true })
    ];

    const mockResults = function(observer: Observer<BudgetDate[]>) {
      observer.next(budgetDates);
      observer.error('...');
      observer.complete;
    };
    const update = new Observable(mockResults).pipe(
      catchError((error: any) => Observable.throw(error))
    );
    return update;
  }

Output: Doesn't include: test service complete

error code running
HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: null, ok: false, …}
getting budget dates from test service
Response =  some return value, maybe null, maybe a good default

Upvotes: 1

Views: 168

Answers (1)

kos
kos

Reputation: 5364

RxJS observable chain would be executed only when subscribed to. So the issue behind output not including test service complete is that you never subscribe to the test service call. Particularly issue is here:

catchError(error => {
  self.budgetTestService.getBudgetDates(self.startDate, self.finishDate)
    .pipe(
      // ...
    );

  // RETURNING OTHER OBSERVABLE HERE
  return of('some return value, maybe null, maybe a good default');
})
// ...
.subscribe(console.log)

Here you call budgetTestService, but its Observable is never subscribed to. Compare it to:

catchError(error => {
  return self.budgetTestService.getBudgetDates(self.startDate, self.finishDate)
    .pipe(
      // ...
    );
})
// ...
.subscribe(console.log)

In the latter code sample we return observable from budgetTestService that will be part of subscription chain.

Check this little example here to compare: "async error handler in RxJS"

Hope this helps

Upvotes: 1

Related Questions