Promise.all comportamento com RxJS Observables?


87

No Angular 1.x, às vezes eu precisava fazer várias httpsolicitações e fazer algo com todas as respostas. Eu jogaria todas as promessas em uma série e ligaria Promise.all(promises).then(function (results) {...}).

As melhores práticas do Angular 2 parecem apontar para o uso de RxJS Observablecomo um substituto para promessas em httpsolicitações. Se eu tiver dois ou mais Observáveis ​​diferentes criados a partir de solicitações http, há um equivalente a Promise.all()?

Respostas:


77

A alternativa mais direta para emular Promise.allé usar o forkJoinoperador (ele inicia todos os observáveis ​​em paralelo e junta seus últimos elementos):

Um pouco fora do escopo, mas caso ajude, no assunto de promessas de encadeamento, você pode usar um simples flatMap: Cf. Composição da promessa RxJS (dados de passagem)


1
Se eu tiver 2 chamadas, uma promessa de retorno e outro retorno observável, posso o usuário forkjoin? ou promessa.all ()? ou ninguém, eu tenho que deixar as 2 funções retornarem o mesmo tipo promessas ou observáveis?
Joe Sleiman

1
Por favor, ajude, forkJoin não funciona quando observáveis ​​passados ​​como parâmetro não emitem valores. Eu anulei Observables e ainda quero usar a funcionalidade forkJoin, mas ela não está funcionando
Goga Koreli

18

Atualização de maio de 2019 usando RxJs v6

Achei as outras respostas úteis e gostaria de oferecer um exemplo para a resposta de Arnaud sobre o zipuso.

Aqui está um trecho mostrando a equivalência entre Promise.alle o rxjs zip(observe também, em rxjs6 como o zip agora é importado usando "rxjs" e não como um operador).

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

A saída de ambos é a mesma. Executar o acima dá:

{ 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 funciona bem também, mas eu prefiro combineLatest, pois você não precisa se preocupar com ele pegando o último valor dos observáveis. Desta forma, você pode apenas ser atualizado sempre que algum deles emitir um novo valor também (por exemplo, você busca em um intervalo ou algo assim).


1
Isso não atende às minhas necessidades atuais, mas com certeza vou usá-lo em breve.
Corey Ogburn

4
Isso não atinge o mesmo comportamento que Promise.all (), mas é semelhante a Promise.any ()
Purrell

Se eu tiver 2 chamadas, uma promessa de retorno e outro retorno observável, posso o usuário forkjoin? ou promessa.all ()? ou ninguém, eu tenho que deixar as 2 funções retornarem o mesmo tipo promessas ou observáveis?
Joe Sleiman

1
@JoeSleiman um pouco tarde, mas você pode escolher o seu lado: Observable.fromPromise () junto com Observable.zip () ou Obserable.toPromise () com Promise.all ()
Arnaud P

11

Em reactivex.io forkJoin realmente aponta para Zip , que fez o trabalho para mim:

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

"isso significa que forkJoin não emitirá mais de uma vez e será concluído depois disso. Se você precisar emitir valores combinados não apenas no final do ciclo de vida dos observáveis ​​passados, mas também ao longo dele, experimente combineLatest ou zip." rxjs-dev.firebaseapp.com/api/index/function/forkJoin
Jeffrey Nicholson Carré

2
forkJoin espera que todos os observáveis ​​terminem, enquanto zip emite um array quando todas as entradas emitem seu primeiro valor. zip pode emitir muitas vezes. Se você tem chamadas http, não faz diferença.
hgoebl

Certo, eu entendo a sutileza agora, saúde. Eu não tinha percebido que as seções de idiomas expandem-_-
Arnaud P
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.