Promise.all perilaku dengan RxJS Observables?

90

Di Angular 1.x saya terkadang perlu membuat beberapa httppermintaan dan melakukan sesuatu dengan semua tanggapan. Saya akan membuang semua janji dalam array dan panggilanPromise.all(promises).then(function (results) {...}) .

Praktik terbaik Angular 2 tampaknya mengarah ke penggunaan RxJS Observablesebagai pengganti promise dalam httppermintaan. Jika saya memiliki dua atau lebih Observable berbeda yang dibuat dari permintaan http, apakah ada yang setara dengan Promise.all()?

Corey Ogburn
sumber

Jawaban:

80

Alternatif yang lebih mudah untuk meniru Promise.alladalah dengan menggunakan forkJoinoperator (ini memulai semua observable secara paralel dan menggabungkan elemen terakhirnya):

Agak di luar ruang lingkup, tetapi jika itu membantu, tentang masalah merangkai janji, Anda dapat menggunakan yang sederhana flatMap: Cf. Komposisi Janji RxJS (meneruskan data)

pengguna3743222
sumber
1
Jika saya memiliki 2 panggilan, satu janji kembali dan satu lagi dapat diamati, bisakah saya menggunakan forkjoin? atau promise.all ()? atau tidak, saya harus membiarkan 2 fungsi mengembalikan tipe yang sama baik promise atau observable?
Joe Sleiman
1
Tolong bantu, forkJoin tidak berfungsi ketika observable yang diteruskan karena parameter tidak mengeluarkan nilai. Saya memiliki Observables yang batal dan masih ingin menggunakan fungsi forkJoin tetapi tidak berfungsi
Goga Koreli
18

Perbarui Mei 2019 menggunakan RxJs v6

Menemukan jawaban lain yang berguna, dan ingin menawarkan contoh untuk jawaban yang ditawarkan oleh Arnaud tentang zip penggunaan.

Berikut ini cuplikan yang menunjukkan kesetaraan antara Promise.alldan rxjs zip(perhatikan juga, di rxjs6 bagaimana zip sekarang diimpor menggunakan "rxjs" & bukan sebagai operator).

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

Output dari keduanya sama. Menjalankan di atas memberikan:

{ 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.dll
sumber
12

forkJoin juga berfungsi dengan baik, tetapi saya lebih suka menggabungkanLatest karena Anda tidak perlu khawatir tentang itu mengambil nilai terakhir yang dapat diamati. Dengan cara ini, Anda bisa mendapatkan pembaruan setiap kali salah satu dari mereka memancarkan nilai baru juga (misalnya Anda mengambil pada interval atau sesuatu).

kakigoori
sumber
1
Ini tidak memenuhi kebutuhan saya saat ini tetapi saya pasti akan segera menggunakannya.
Corey Ogburn
5
Itu tidak mencapai perilaku yang sama seperti Promise.all (), tetapi mirip dengan Promise.any ()
Purrell
Jika saya memiliki 2 panggilan, satu janji kembali dan satu lagi dapat diamati, bisakah saya menggunakan forkjoin? atau promise.all ()? atau tidak, saya harus membiarkan 2 fungsi mengembalikan tipe yang sama baik promise atau observable?
Joe Sleiman
1
@JoeSleiman agak terlambat, tetapi Anda dapat memilih: Observable.fromPromise () bersama dengan Observable.zip () , atau Obserable.toPromise () dengan Promise.all ()
Arnaud P
11

Di reactivex.io forkJoin sebenarnya menunjuk ke Zip , yang melakukan pekerjaan itu untuk saya:

let subscription = Observable.zip(obs1, obs2, ...).subscribe(...);
Arnaud P.
sumber
"itu berarti forkJoin tidak akan memancarkan lebih dari sekali dan akan selesai setelah itu. Jika Anda perlu memancarkan nilai gabungan tidak hanya di akhir siklus hidup dari observable yang lewat, tetapi juga di seluruh itu, coba gabungkanLatest atau zip sebagai gantinya." rxjs-dev.firebaseapp.com/api/index/function/forkJoin
Jeffrey Nicholson Carré
3
forkJoin menunggu semua observable untuk berakhir, sementara zip memancarkan array ketika semua input mengeluarkan nilai pertamanya. zip mungkin memancarkan berkali-kali. Jika Anda memiliki http-call, tidak ada bedanya.
hgoebl
Benar, saya mengerti sekarang, tepuk tangan. Saya tidak menyadari bahwa bagian bahasa berkembang-_-
Arnaud P