Promise.all поведінка з RxJS Observables?


87

У Angular 1.x мені іноді доводиться робити кілька httpзапитів і робити щось із усіма відповідями. Я б кинув усі обіцянки в масив і зателефонував Promise.all(promises).then(function (results) {...}).

Здається, найкращі практики Angular 2 вказують на використання RxJS Observableяк заміну обіцянкам у httpзапитах. Якщо у мене є дві або більше різних спостережливих даних, створених із запитів http, чи є це еквівалент Promise.all()?

Відповіді:


77

Більш простою альтернативою для емуляції Promise.allє використання forkJoinоператора (він запускає всі спостережувані паралельно і об’єднує їх останні елементи):

Трохи поза сферою дії, але у випадку, якщо це допомагає, щодо об'єднання обіцянок можна скористатися простим flatMap: Пор. RxJS Promise Composition (передача даних)


1
якщо у мене є 2 дзвінки, одне обіцяне повернення, а інше спостережуване повернення, чи можу я користувач forkjoin? або promis.all ()? чи нікому, я повинен дозволити 2-м функціям повертати один і той самий тип або обіцянки, або спостережувані?
Джо Слейман,

1
Будь ласка, допоможіть, forkJoin не працює, коли спостережувані дані, передані як параметр, не видають значень. У мене є void Observables і я все ще хочу використовувати функцію forkJoin, але вона не працює
Goga Koreli

18

Оновіть травень 2019 року, використовуючи RxJs v6

Інші відповіді знайшли корисними та хотіли запропонувати приклад відповіді Арно про zipвикористання.

Ось фрагмент, що показує еквівалентність між Promise.allі 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!' ]

13

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


1
Це не відповідає моїм поточним потребам, але я точно скористаюся цим найближчим часом.
Кори Огберн,

4
Це не дає такої поведінки, як Promise.all (), але це схоже на Promise.any ()
Перрелл

якщо у мене є 2 дзвінки, одне обіцяне повернення, а інше спостережуване повернення, чи можу я користувач forkjoin? або promis.all ()? чи нікому, я повинен дозволити 2-м функціям повертати один і той самий тип або обіцянки, або спостережувані?
Джо Слейман,

1
@JoeSleiman трохи пізно, але ви можете вибрати свій бік: Observable.fromPromise () разом з Observable.zip () , або Obserable.toPromise () з Promise.all ()
Arnaud P

11

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

let subscription = Observable.zip(obs1, obs2, ...).subscribe(...);

"це означає, що forkJoin не буде випускати більше одного разу, і після цього він завершиться. Якщо вам потрібно випустити комбіновані значення не лише в кінці життєвого циклу переданих спостережуваних, а й упродовж нього, спробуйте замість цього замістити комбінований або zip." rxjs-dev.firebaseapp.com/api/index/function/forkJoin
Джеффрі Ніколсон Карре

2
forkJoin чекає закінчення всіх спостережуваних, тоді як zip видає масив, коли всі входи видають своє перше значення. zip може виділятися багато разів. Якщо у вас є http-дзвінки, це не має значення.
hgoebl

Правильно, я зараз відчуваю тонкощі, ура. Я не розумів, що мовні розділи розширюються-_-
Arnaud P
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.