Поведение Promise.all с помощью RxJS Observables?

87

В Angular 1.x мне иногда приходилось делать несколько httpзапросов и что-то делать со всеми ответами. Я бы бросил все обещания в массив и позвонил Promise.all(promises).then(function (results) {...}).

Лучшие практики Angular 2, похоже, указывают на использование RxJS Observableв качестве замены обещаний в httpзапросах. Если у меня есть два или более разных Observable, созданных из HTTP-запросов, есть ли эквивалент Promise.all()?

Кори Огберн
источник

Ответы:

77

Более простой альтернативой эмуляции Promise.allявляется использование forkJoinоператора (он запускает все наблюдаемые параллельно и соединяет их последние элементы):

Немного выходит за рамки, но в случае, если это помогает, в отношении цепочки обещаний вы можете использовать простое flatMap: Cf. RxJS Promise Composition (передача данных)

user3743222
источник
1
Если у меня есть 2 вызова, одно обещание возврата и другое наблюдаемое возвращение, могу ли я использовать forkjoin? или Promise.all ()? или никто, я должен позволить двум функциям возвращать один и тот же тип: обещания или наблюдаемые?
Joe Sleiman
1
Пожалуйста, помогите, forkJoin не работает, если наблюдаемые, переданные в качестве параметра, не выдают значений. У меня есть void Observables, и я все еще хочу использовать функциональность forkJoin, но она не работает
Гога Корели
18

Обновление мая 2019 с использованием RxJs v6

Считал другие ответы полезными и хотел предложить пример ответа, предложенного Арно об zipиспользовании.

Вот фрагмент, показывающий эквивалентность между Promise.allrxjs и rxjs zip(обратите внимание также, что в rxjs6 zip теперь импортируется с использованием rxjs, а не как оператора).

import { zip } from "rxjs";

const the_weather = new Promise(resolve => {
  setTimeout(() => {
    resolve({ temp: 29, conditions: "Sunny with Clouds" });
  }, 2000);
});

const the_tweets = new Promise(resolve => {
  setTimeout(() => {
    resolve(["I like cake", "BBQ is good too!"]);
  }, 500);
});

// Using RxJs
let source$ = zip(the_weather, the_tweets);
source$.subscribe(([weatherInfo, tweetInfo]) =>
  console.log(weatherInfo, tweetInfo)
);

// Using ES6 Promises
Promise.all([the_weather, the_tweets]).then(responses => {
  const [weatherInfo, tweetInfo] = responses;
  console.log(weatherInfo, tweetInfo);
});

Результат обоих одинаков. Выполнение вышеуказанного дает:

{ temp: 29, conditions: 'Sunny with Clouds' } [ 'I like cake', 'BBQ is good too!' ]
{ temp: 29, conditions: 'Sunny with Clouds' } [ 'I like cake', 'BBQ is good too!' ]
Arcseldon
источник
13

forkJoin тоже работает нормально, но я бы предпочел combLatest, поскольку вам не нужно беспокоиться о том, что он принимает последнее значение наблюдаемых. Таким образом, вы можете просто получать обновления всякий раз, когда какой-либо из них также генерирует новое значение (например, вы выбираете через интервал или что-то в этом роде).

какигури
источник
1
Это не соответствует моим текущим потребностям, но я обязательно им скоро воспользуюсь.
Кори Огберн
4
Это не обеспечивает такого же поведения, как Promise.all (), но похоже на Promise.any ()
Пуррелл
Если у меня есть 2 вызова, одно обещание возврата и другое наблюдаемое возвращение, могу ли я использовать forkjoin? или Promise.all ()? или никто, я должен позволить двум функциям возвращать один и тот же тип: обещания или наблюдаемые?
Joe Sleiman
1
@JoeSleiman немного опоздал, но вы можете выбрать свою сторону: Observable.fromPromise () вместе с Observable.zip () или Obserable.toPromise () с Promise.all ()
Арно П.
11

На reactivex.io forkJoin фактически указывает на Zip , который выполнил всю работу за меня:

let subscription = Observable.zip(obs1, obs2, ...).subscribe(...);
Арно П.
источник
"это означает, что forkJoin не будет генерировать более одного раза, и он завершится после этого. Если вам нужно генерировать комбинированные значения не только в конце жизненного цикла переданных наблюдаемых, но и на протяжении всего его, попробуйте вместо этого комбинироватьLatest или zip." rxjs-dev.firebaseapp.com/api/index/function/forkJoin
Джеффри Николсон Карре
2
forkJoin ожидает завершения всех наблюдаемых, в то время как zip генерирует массив, когда все входы выдают свое первое значение. zip может выдавать много раз. Если у вас http-звонки, то никакой разницы.
hgoebl
Хорошо, теперь я уловил тонкость, ура. Я не осознавал, что языковые разделы расширяются-_-
Арно П.