Passing through multiple parameters to rxjs operator

12,952

Solution 1

Use forkJoin, it's designed for this type of situation.

Solution 2

Using forkJoin:

.pipe(
  mergeMap((appVersion) => forkJoin(
    of(appVersion),
    this.storage.get('access_token').take(1)
  )),
  mergeMap(([version, token]) => {
    this.createHeaders(version, token)
  })
)

But even easier with withLatestFrom:

.pipe(
  withLatestFrom(this.storage.get('access_token')),
  mergeMap(([version, token]) => {
    this.createHeaders(version, token)
  })
)

I have included both because withLatestFrom is easier but forkJoin should be used where you need to access the initial parameter. For example, if you were doing this.storage.get(appVersion)

Solution 3

You may want to try something like this

private getHeaders(): Observable<any> {
  return this.appInfo.getVersion()
    .pipe(
      mergeMap(version => this.storage.get('access_token')
                          .map(token => ({version, token})),
      map(data => this.createHeaders(data.version, data.token))
    );
}

ALTERNATIVE VERSION WITH ZIP

private getHeaders(): Observable<any> {
  const versionObs = this.appInfo.getVersion();
  const tokenObs = this.storage.get('access_token');
  return Observable.zip(versionObs, tokenObs)
    .pipe(
      map(data => this.createHeaders(data[0], data[1]))
    );
}
Share:
12,952
uloco
Author by

uloco

Hey there! I’m Umut, nice to meet you! I am a Senior Sotware Engineer focused on UI and UX development &amp; design, currently working at Smokeless in Munich, Germany. Things I like JavaScript • TypeScript • React • ReasonML • Functional Programming • Web Development • MacOS • Linux • NeoVim • Git • Test Driven Development • Visual Studio Code • Open Source Software • Shell • DevOps • Tooling Things I also like Drawing • Painting • Playing Guitar • Singing • Curating Playlists • Instrumental Music • Writing • Reading • Cooking • Philosophy • Psychology • Mechanical Keyboards • Personal Development • Gaming • People

Updated on June 25, 2022

Comments

  • uloco
    uloco almost 2 years

    Is there a more elegant way of doing the following?

    private getHeaders(): Observable<any> {
      let version;
      let token;
      return this.appInfo.getVersion()
        .pipe(
          tap(appVersion => version = appVersion),
          mergeMap(() => this.storage.get('access_token')),
          tap(accessToken => token = accessToken),
          mergeMap(accessToken => of(this.createHeaders(version, token)))
        );
    }
    

    How can I more fluently remember the two return values of this.appInfo.getVersion() and this.storage.get('access_token') without writing them to temporary variables with the power of rxjs?

    Perhaps merging some observables into one? There are so many rxjs operators and stuff...

  • uloco
    uloco about 6 years
    I think this should work, but it is not elegant imho... The two observable sequences could be done in parallel. Is zip the right tool for this?
  • Picci
    Picci about 6 years
    You are right. You can zip too. I have updated the answer
  • John White
    John White over 5 years
    forkJoin seems deprecated
  • brz
    brz over 3 years
    With RxJS 5 you would use the resultSelector argument of mergeMap. In RxJS 6 the resultSelector is deprecated and they advice you to use "inner map" as an alternative. I think it's a matter of preference but I like the "map" option more than the "zip" option. But I may be biased because I'm mainly a C# developer...
  • danday74
    danday74 about 3 years
    forkJoin is not deprecated, it just takes an array now instead of comma separated args - the old comma separated args approach is deprecated