Reputation: 3801
I am using RxJS. I have two Observables (API calls) that return a different amount of information for the same array. I want to switch between the Observables and have the subscription recognize both results, i.e. fire each time a value is returned.
Here's an example using Typescript (this does not work):
let foo = [];
const callOne$ = this.service.getSomeData$; // this should take 0.5 seconds
const callTwo$ = this.service.getAllTheData$; // this should take 6 seconds
callOne$.pipe(
switchMap(data => data.length > 0 ? callTwo$ : of(data)
).subscribe(data => {
console.log(data); // this fires once but I want it to fire twice
foo = data;
});
The above example retrieves callOne$
, then retrieves callTwo$
, and then gives me the result. Instead I want the results of both in order. How would I subscribe to the Observables so that the first result is received and then updated by the second call?
Upvotes: 0
Views: 477
Reputation: 3801
I discovered the best result is to use concat()
, which responds to Observable results in order.
In other words:
concat(callOne$, callTwo$)
.subscribe(data => {
console.log(data); // this will fire twice
foo = data;
});
This code will return two results for data
, updating the variable in the order of the concat()
list.
Upvotes: 0
Reputation: 17762
The simplest way may be
merge(callOne$, callTwo$)
.subscribe(data => {
console.log(data); // this fires twice but results are not guaranteed to be ordered
foo = data;
});
You can keep the order but have a single event emitted with something like this
forkJoin(callOne$, callTwo$)
.subscribe(([data1, data2]) => { // this fires once with both results ordered
console.log(data1);
console.log(data2);
foo = data;
});
If you want to have 2 separate notification maintaining the order, i.e. first the result of callOne$ and then the result of callTwo$, you may try to use the expand
operator like this
callOne$.pipe(
expand(val => callTwo$),
take(2) // to make sure you do not call callTwo$ infinitely
)
.subscribe(data => {
console.log(data); // this fires twice and the results are guaranteed to be ordered
foo = data;
});
Looking at the fact that foo
is an array, you may be inclined to the use of forkJoin
, i.e. the second option.
You may find a more detailed explanation in this article.
Upvotes: 1