Передача нескольких параметров оператору rxjs

Есть ли более элегантный способ сделать следующее?

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)))
    );
}

Как я могу больше бегло запомнить два возвращаемых значения this.appInfo.getVersion() и this.storage.get('access_token'), не записывая их во временные переменные с помощью rxjs?

Возможно, объединить несколько наблюдаемых в одну? Так много операторов rxjs и прочего ...

forkJoin используется именно для этой цели.
LordAlpaca 11.04.2018 14:23

Работает! Большое спасибо :)))) Пожалуйста, напишите ответ, чтобы я мог принять;)

uloco 11.04.2018 14:28

withLatestFrom здесь проще - см. мой ответ - отличный вопрос кстати +1

danday74 11.08.2018 00:36
12
3
10 767
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете попробовать что-то вроде этого

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))
    );
}

АЛЬТЕРНАТИВНАЯ ВЕРСИЯ С 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]))
    );
}

Я думаю, это должно сработать, но это не изящно, imho ... Две наблюдаемые последовательности могут выполняться параллельно. Подходит ли для этого zip?

uloco 11.04.2018 14:23

Ты прав. Вы тоже можете zip. Я обновил ответ

Picci 11.04.2018 15:19

С RxJS 5 вы должны использовать аргумент resultSelector для mergeMap. В RxJS 6 resultSelector устарел, и они советуют вам использовать «внутреннюю карту» в качестве альтернативы. Я думаю, это дело предпочтений, но мне нравится опция «карта» больше, чем опция «zip». Но я могу быть предвзятым, потому что я в основном разработчик на C# ...

breez 28.10.2020 07:52
Ответ принят как подходящий

Используйте forkJoin, он разработан для таких ситуаций.

Использование forkJoin:

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

Но с withLatestFrom еще проще:

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

Я включил оба, потому что withLatestFrom проще, но forkJoin следует использовать там, где вам нужно получить доступ к начальному параметру. Например, если вы делали this.storage.get(appVersion)

forkJoin кажется устаревшим

John White 17.01.2019 13:05

forkJoin не является устаревшим, теперь он просто принимает массив вместо аргументов, разделенных запятыми - старый подход с аргументами, разделенными запятыми, не рекомендуется

danday74 11.02.2021 03:10

Другие вопросы по теме