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()?

Corey Ogburn
fonte

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)

user3743222
fonte
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!' ]
Arceldon
fonte
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).

kakigoori
fonte
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(...);
Arnaud P
fonte
"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