gog
gog

Reputation: 13008

how to use result of first observable into next observables?

I have this method:

 zip(
  this.$one.getOne(id)
     .pipe(switchMap(oneResult => {
        return this.$two.getTwo(oneResult.id)
      }))
     .pipe(switchMap(twoResult => {
        // Here I Would like to use the **oneResult** as argument to the $three observable too.
        return this.$three.getThree(oneResult.id)
     })),
   this.$four.getFour()
 ).subscribe(zipResult => {
     [getTwoResult, getThreeResult]
 }

How do I pass the $one Observable result to $two Observable and $hree observable? I can just get it on the first switchMap.

Upvotes: 4

Views: 4218

Answers (1)

Alexander Staroselsky
Alexander Staroselsky

Reputation: 38847

You an use map on the switchMap to create a "resultSelector". switchMap has a resultSelector function that can be used to create the same effect, but this may get deprecated in future versions of RxJS in lieu of using map as the below answer demonstrates. You'd effectively be packaging oneResult and twoResult into an object or array for use in the second switchMap. You could keep doing this as far down the stream as you'd need. It would look like something like this (I've added delays to simulate API calls):

import { Component } from '@angular/core';
import { Observable, of, zip } from 'rxjs';
import { map, switchMap, delay } from 'rxjs/operators';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  name = 'Angular';

  getOne(id: string): Observable<string> {
    return of('foo').pipe(delay(1000));
  }

  getTwo(id: string): Observable<string> {
    return of('bar').pipe(delay(1000));
  }

  getThree(id: string): Observable<string> {
    return of('baz').pipe(delay(1000));
  }

  getFour(id: string): Observable<string> {
    return of('foobar').pipe(delay(1000));
  }


  ngOnInit(): void {
    zip(
      this.getOne('foo').pipe(
        switchMap(oneResult =>
          this.getTwo(oneResult).pipe(
            map(twoResult => ({ oneResult, twoResult }))
          )
        ),
        switchMap(oneTwoResult => {
          console.log(oneTwoResult);
          return this.getThree(oneTwoResult.oneResult);
        })
      ),
      this.getFour('foobar')
    )
    .subscribe(result => console.log(result));
  }
}

Using resultSelector function of switchMap:

zip(
  this.getOne('foo').pipe(
    switchMap(oneResult =>
      this.getTwo(oneResult),
      (oneResult, twoResult) => ({ oneResult, twoResult })
    ),
    switchMap(oneTwoResult => {
      console.log('oneTwoResult: ', oneTwoResult);
      return this.getThree(oneTwoResult.oneResult)
    })
  ),
  this.getFour('foobar')
)
.subscribe(result => console.log(result));

Here is a StackBlitz showing this functionality in action.

Hopefully that helps!

Upvotes: 3

Related Questions