Rxjs - переназначить объект с наблюдаемыми в качестве значений - PullRequest
0 голосов
/ 11 декабря 2018

У меня есть такая наблюдаемая:

  const original = Observable.of({
    a: this.http.get('https://jsonplaceholder.typicode.com/todos/11'),
    b: this.http.get('https://jsonplaceholder.typicode.com/todos/22'),
    c: this.http.get('https://jsonplaceholder.typicode.com/todos/33')
  });

Мне нужно разрешить внутренние наблюдаемые и получить что-то вроде этого в обработчике подписки:

  {
    a: ResponseFromServer,
    b: ResponseFromServer,
    c: ResponseFromServer,
  }

Как мне подойти к этомупроблема?

Спасибо.

РЕДАКТИРОВАТЬ: Я понял это, прочитайте ниже.

Кажется, что не многие люди знают, что * операторы карты раньше имели что-то под названиемresultSelector в качестве второго аргумента.Теперь в rxjs v6 вы можете сделать то же самое с inner map, позвольте мне показать вам.

const original = Observable.of({
    a: this.http.get('https://jsonplaceholder.typicode.com/todos/11'),
    b: this.http.get('https://jsonplaceholder.typicode.com/todos/22'),
    c: this.http.get('https://jsonplaceholder.typicode.com/todos/33')
});

const transformed = original.pipe(
    mergeMap(sourceValue => 
        forkJoin(_.values(sourceValue)).pipe(map(resolvedHttpRequests => {
            // here you have access to sourceValue as well as resolvedHttpRequests so you can do manual join to match the data.
        }))
    )
)

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

Если исходный объект уже содержит Observables, вы можете сделать это, например, следующим образом (очевидно, есть несколько способов сделать это):

const mockXHRCall = (url: string) => {
  return of('response');
};

const original = of({
  a: mockXHRCall('https://jsonplaceholder.typicode.com/todos/11'),
  b: mockXHRCall('https://jsonplaceholder.typicode.com/todos/22'),
  c: mockXHRCall('https://jsonplaceholder.typicode.com/todos/33')
}).pipe(
  mergeMap(obj => {
    const observables$ = Object.keys(obj).map(key => obj[key].pipe(
      map(response => (
        { [key]: response } // wrap the response with eg. { c: ResponseFromC }
      )),
    ));

    return merge(...observables$);
  }),
  scan((acc, wrapped) => (
    { ...acc, ...wrapped }
  ), {}),
  takeLast(1),
).subscribe(console.log);

scan собирает все ответы и объединяет их водин объект.

Демонстрация в реальном времени: https://stackblitz.com/edit/rxjs-ffza8b

0 голосов
/ 11 декабря 2018

То, как вы делаете это выше (с Observable.of), по сути создает Наблюдаемость более высокого уровня из более низких Наблюдаемых.

Я думаю, что лучшим оператором будет forkJoin, поскольку каждая из этих наблюдаемых холодна и конечна, а forkJoin фиксирует первое излучение каждой наблюдаемой и выдает все значения, когда все завершены:

  const original = forkJoin([
    this.http.get('https://jsonplaceholder.typicode.com/todos/11'),
    this.http.get('https://jsonplaceholder.typicode.com/todos/22'),
    this.http.get('https://jsonplaceholder.typicode.com/todos/33')
  ]);

  let result = {a: null, b: null, c: null};

  original.subscribe([a,b,c] => result = {a,b,c});

Просто обратите внимание, что испускаемый элемент из forkJoinбудет массивом, индекс которого совпадает с индексами переданных в Observables.

...