-1
this.httpService
          .getCustomer(id)
          .pipe(
            switchMap((customerObj) => this.httpService.getCustomerAccount(customerObj.account_id)),
            switchMap((accountObj) =>
              this.httpService.getAccountHoliday(accountObj.holiday_id),
            ),
          )
          .subscribe((holidays: Holiday[]) => {
            for (const holiday of holidays) {
              this.httpService.getDestination(holiday.dest_id).subscribe((destination) => {
                if (holiday.identifier === destination.name) {
                  console.log(holiday);
                }
              });
            }
          });

I want to do something like this

  this.httpService
      .getCustomer(id)
      .pipe(
        switchMap((customerObj) => this.httpService.getCustomerAccount(customerObj.account_id)),
        switchMap((accountObj) =>
          this.httpService.getAccountHoliday(accountObj.holiday_id),
        ),
        filter(holiday => this.httpService.getDestination(holiday.dest_id).name === holiday.identifier)
      )
      .subscribe((holiday: Holiday[]) => {
        for (const holiday of holidays) {
          console.log(holiday);
        }
      });

That is, merge the logic of for loop with the overservables i.e I need to filter out the holidays before I subscribe. How can I do this?

asdfkjasdfjk
  • 3,784
  • 18
  • 64
  • 104
StaticName
  • 239
  • 1
  • 2
  • 10

2 Answers2

2

Something like this? You can merge your looped calls in a switchMap.

Not sure if this compiles perfectly as I don't have your code, but something similar should do the trick.

this.httpService.getCustomer(id).pipe(
  
  switchMap(customerObj => 
    this.httpService.getCustomerAccount(customerObj.account_id)
  ),

  switchMap(accountObj =>
    this.httpService.getAccountHoliday(accountObj.holiday_id),
  ),

  map((holidays: Holiday[]) => holidays.map(holiday => 
    this.httpService.getDestination(holiday.dest_id).pipe(
      filter(destination => holiday.identifier === destination.name),
      mapTo(holiday)
    )
  )),

  switchMap(filteredHolidays => merge(...filteredHolidays)),

).subscribe(console.log);

You can also forkJoin instead of merge to get an array back all at once. The tricky bit here is that forkJoin doesn't know what to do with an observable that completes without emitting, so we can't filter until after the forkJoin. The workaround in this case is to map responses we're not interested in to null, then filter null values after.

That might look something like this:

this.httpService.getCustomer(id).pipe(

  switchMap(customerObj => 
    this.httpService.getCustomerAccount(customerObj.account_id)
  ),

  switchMap(accountObj =>
    this.httpService.getAccountHoliday(accountObj.holiday_id),
  ),

  map((holidays: Holiday[]) => holidays.map(holiday => 
    this.httpService.getDestination(holiday.dest_id).pipe(
      map(destination => 
        holiday.identifier === destination.name ?
        holiday : null
      )
    )
  )),

  switchMap(mappedHolidays => forkJoin(mappedHolidays)),

  map(mappedHolidays => mappedHolidays.filter(v => v != null))

).subscribe(holidays => holidays.forEach(console.log));
Mrk Sef
  • 7,557
  • 1
  • 9
  • 21
  • The output should be holidays but they are filtered against the destination. Each holiday has multiple destination and if the `holiday.identifier === destination.name` then the holiday should be in result – asdfkjasdfjk Aug 20 '21 at 19:16
  • @asdfkjasdfjk AH, I see. Then it's almost the same. I updated my answer for another possible solution. – Mrk Sef Aug 20 '21 at 19:50
0

Try it like this:

this.httpService
    .getCustomer(id)
    .pipe(
        switchMap((customerObj) => 
            this.httpService.getCustomerAccount(customerObj.account_id)),
        switchMap((accountObj) =>
            this.httpService.getAccountHoliday(accountObj.holiday_id)
                .pipe(
                    switchMap((holiday) => 
                      combineLatest([
                          of(members),                          
                          this.httpService
                              .getDestination(holiday.dest_id)
                      ])
                    ),
                    map(([holiday, dest]) => {
                        if (dest.identifier === dest.name){
                            return holiday
                            /* all holidays not matching the condition 
                            are now undefined */ 
                        }
                    }
                ),
        ),
        map((holidays: (Holiday | undefined)[]) => 
           holidays.filter(h => !!h) // filter out undefined holidays
        ),
     ).subscribe((holidays: Holiday []) => {
         console.log(holidays)  
     });
Tobias S.
  • 21,159
  • 4
  • 27
  • 45
  • The output should be holidays but they are filtered against the destination. Each holiday has multiple destination and if the `holiday.identifier === destination.name` then the holiday should be in result – asdfkjasdfjk Aug 20 '21 at 19:17
  • hmm i see it's still not working since holiday on line 9 would be an array of holidays – Tobias S. Aug 20 '21 at 19:32