Promise.all hành vi với RxJS Observables?


87

Trong Angular 1.x, đôi khi tôi cần thực hiện nhiều httpyêu cầu và thực hiện điều gì đó với tất cả các phản hồi. Tôi sẽ ném tất cả các lời hứa vào một mảng và cuộc gọi Promise.all(promises).then(function (results) {...}).

Các phương pháp hay nhất của Angular 2 dường như hướng tới việc sử dụng RxJS Observableđể thay thế cho các lời hứa trong httpyêu cầu. Nếu tôi có hai hoặc nhiều Observables khác nhau được tạo từ các yêu cầu http, thì có tương đương với Promise.all()?

Câu trả lời:


77

Cách thay thế đơn giản hơn cho việc mô phỏng Promise.alllà sử dụng forkJointoán tử (nó bắt đầu tất cả các có thể quan sát song song và nối các phần tử cuối cùng của chúng):

Một chút ngoài phạm vi, nhưng trong trường hợp nó hữu ích, về chủ đề chuỗi lời hứa, bạn có thể sử dụng đơn giản flatMap: Cf. RxJS Promise Composition (truyền dữ liệu)


1
Nếu tôi có 2 cuộc gọi, một lời hứa trả lại và một lần trả lại có thể quan sát được, tôi có thể sử dụng forkjoin không? hoặc Promise.all ()? hoặc không có ai, tôi phải để 2 hàm trả về cùng một kiểu hoặc là hứa hẹn hoặc có thể quan sát được?
Joe Sleiman

1
Vui lòng giúp đỡ, forkJoin không hoạt động khi các đối tượng quan sát được truyền dưới dạng tham số không phát ra giá trị. Tôi có khoảng trống quan sát và vẫn muốn sử dụng chức năng forkJoin nhưng nó không làm việc
Goga Koreli

18

Cập nhật tháng 5 năm 2019 bằng RxJs v6

Tìm thấy các câu trả lời khác hữu ích và muốn cung cấp một ví dụ cho câu trả lời do Arnaud đưa ra về zipcách sử dụng.

Đây là một đoạn mã cho thấy sự tương đương giữa Promise.allvà rxjs zip(cũng lưu ý, trong rxjs6, cách zip bây giờ được nhập bằng cách sử dụng "rxjs" chứ không phải dưới dạng toán tử).

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

Đầu ra từ cả hai đều giống nhau. Chạy ở trên cho:

{ 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 hoạt động tốt quá, nhưng tôi muốn combineLatest vì bạn không cần phải lo lắng về nó lấy giá trị cuối cùng của quan sát. Bằng cách này, bạn chỉ có thể được cập nhật bất cứ khi nào chúng cũng phát ra một giá trị mới (ví dụ: bạn tìm nạp vào một khoảng thời gian hoặc một cái gì đó).


1
Điều này không đáp ứng nhu cầu hiện tại của tôi nhưng tôi chắc chắn sẽ sớm sử dụng nó.
Corey Ogburn

4
Điều đó không đạt được hành vi giống như Promise.all (), nhưng nó tương tự với Promise.any ()
Purrell

Nếu tôi có 2 cuộc gọi, một lời hứa trả lại và một lần trả lại có thể quan sát được, tôi có thể sử dụng forkjoin không? hoặc Promise.all ()? hoặc không có ai, tôi phải để 2 hàm trả về cùng một kiểu hoặc là hứa hẹn hoặc có thể quan sát được?
Joe Sleiman

1
@JoeSleiman hơi muộn, nhưng bạn có thể chọn phụ của bạn: Observable.fromPromise () cùng với Observable.zip () , hoặc Obserable.toPromise () với Promise.all ()
Arnaud P

11

Trên reactivex.io forkJoin thực sự điểm Zip , mà đã làm công việc cho tôi:

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

"điều đó có nghĩa là forkJoin sẽ không phát ra nhiều lần và nó sẽ hoàn thành sau đó. Nếu bạn cần phát ra các giá trị kết hợp không chỉ ở cuối vòng đời của các đối tượng quan sát đã qua mà còn trong suốt vòng đời của nó, hãy thử dùng connectLatest hoặc zip để thay thế." rxjs-dev.firebaseapp.com/api/index/ Chức năng/forkJoin
Jeffrey Nicholson Carré

2
forkJoin đợi tất cả các có thể quan sát kết thúc, trong khi zip phát ra một mảng khi tất cả các đầu vào phát ra giá trị đầu tiên của chúng. zip có thể phát ra nhiều lần. Nếu bạn có các cuộc gọi http, điều đó không có gì khác biệt.
hgoebl

Đúng rồi, tôi có được sự tinh tế bây giờ, chúc mừng. Tôi đã không nhận ra rằng các phần ngôn ngữ mở rộng-_-
Arnaud P
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.