Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to 'wait' for two observables in RxJS

In my app i have something like:

this._personService.getName(id)       .concat(this._documentService.getDocument())       .subscribe((response) => {                   console.log(response)                   this.showForm()        });   //Output:   // [getnameResult]  // [getDocumentResult]   // I want:  // [getnameResult][getDocumentResult] 

Then i get two separated results, first of the _personService and then the _documentService. How can I wait for both results before call this.showForm() to finish an then manipulate the results of each one.

like image 666
gog Avatar asked May 16 '17 14:05

gog


People also ask

How do I combine two Observables RxJS?

The RxJS merge() operator is a join operator that is used to turn multiple observables into a single observable. It creates an output Observable, which concurrently emits all values from every given input Observables.

How do I subscribe to two Observables?

In our component, we use forkJoin to combine the Observables into a single value Observable. The forkJoin operator will subscribe to each Observable passed into it. Once it receives a value from all the Observables, it will emit a new value with the combined values of each Observable.

What is the difference between combineLatest and forkJoin?

forkJoin - When all observables complete, emit the last emitted value from each. combineLatest - When any observable emits a value, emit the latest value from each.

Which method is used in RxJS to work on multiple operators together in sequential order?

ConcatAll This operator combines all emitted inner streams and just as with plain concat sequentially produces values from each stream.


2 Answers

Last Update: Jun, 2021.

RxJS v7: combineLatestWith

From reactiveX documentation:

Whenever any input Observable emits a value, it computes a formula using the latest values from all the inputs, then emits the output of that formula.

// Observables to combine const name$ = this._personService.getName(id); const document$ = this._documentService.getDocument();      name$.pipe(         combineLatestWith((name, document) => {name, document})       )       .subscribe(pair => {            this.name = pair.name;            this.document = pair.document;            this.showForm();        }) 

(Deprecated) RxJS v6 combineLatest()

From reactiveX documentation:

Whenever any input Observable emits a value, it computes a formula using the latest values from all the inputs, then emits the output of that formula.

(Update: Feb, 2021):

// Deprecated (RxJS v6) // Observables to combine const name$ = this._personService.getName(id); const document$ = this._documentService.getDocument();      name$.combineLatest(document$, (name, document) => {name, document})     .subscribe(pair => {            this.name = pair.name;            this.document = pair.document;            this.showForm();        }) 

(alternate syntax): combineLatest(observables)

// Deprecated (RxJS v6) // Observables to combine const name$ = this._personService.getName(id); const document$ = this._documentService.getDocument();      combineLatest(name$, document$, (name, document) => ({name, document}))     .subscribe(pair => {            this.name = pair.name;            this.document = pair.document;            this.showForm();        }) 

zip vs combineLatest

(Update: Oct, 2018) I previously suggested the use of zip method. However, for some use cases, combineLatest has a few advantages over zip. So it is important to understand the differences.

CombineLatest emits the latest emitted values from observables. While zip method emits the emitted items in sequence order.

For example if observable #1 emits its 3rd item and observable #2 has emitted its 5th item. The result using zip method will be the 3rd emitted values of both observables.

In this situation the result using combineLatest will be the 5th and 3rd. which feels more natural.


Observable.zip(observables)

(Original answer: Jul, 2017) Observable.zip method is explained in reactiveX documentation:

Combines multiple Observables to create an Observable whose values are calculated from the values, in order, of each of its input Observables.

// Observables to combine const name$ = this._personService.getName(id); const document$ = this._documentService.getDocument();      Observable     .zip(name$, document$, (name: string, document: string) => ({name, document}))     .subscribe(pair => {            this.name = pair.name;            this.document = pair.document;            this.showForm();        }) 

a side note (applies for both methods)

The last parameter, where we have provided a function, (name: string, document: string) => ({name, document}) is optional. You can skip it, or do more complex operations:

If the latest parameter is a function, this function is used to compute the created value from the input values. Otherwise, an array of the input values is returned.

So if you skip the last part, you get an array:

// Observables to combine const name$ = this._personService.getName(id); const document$ = this._documentService.getDocument();      Observable     .zip(name$, document$)     .subscribe(pair => {            this.name = pair['0'];            this.document = pair['1'];            this.showForm();        }) 
like image 127
Hamid Asghari Avatar answered Sep 18 '22 16:09

Hamid Asghari


Use forkJoin() method of observables. Check this link for reference

From the RXJS docs

This operator is best used when you have a group of observables and only care about the final emitted value of each. One common use case for this is if you wish to issue multiple requests on page load (or some other event) and only want to take action when a response has been receieved for all. In this way it is similar to how you might use Promise.all

forkJoin([character, characterHomeworld]).subscribe(results => {   // results[0] is our character   // results[1] is our character homeworld   results[0].homeworld = results[1];   this.loadedCharacter = results[0]; }); 

Code taken from: https://coryrylan.com/blog/angular-multiple-http-requests-with-rxjs

like image 45
Prathmesh Dali Avatar answered Sep 18 '22 16:09

Prathmesh Dali