Reputation: 1147
I have two different API endpoints. One returns a Cards
object, the other an Array of Cards
objects. What I want to do is get the first Card as the first element in the Array from the second endpoint. Is there any way to do that? Both are observables returned from HTTPClient
, so maybe it would be simple to do with some operator, but I don't know enough to do that yet. Just to illustrate it better:
I have:
latestCards$: Observable<Cards> = http.get('latestCardsEndpoint');
// { title: 'Latest', cards: [], ... }
featuredCards$: Observable<Cards[]> = http.get('featuredCardsEndpoint');
// [
// { title: 'Featured1', cards: [], ... },
// { title: 'Featured2', cards: [], ... },
// ...
// ]
I need
homeCards$: Observable<Cards[]>;
// [
// { title: 'Latest', cards: [], ... },
// { title: 'Featured1', cards: [], ... },
// { title: 'Featured2', cards: [], ... },
// ...
// ]
Upvotes: 1
Views: 3156
Reputation: 28434
Sure:
Naive approach:
import {forkJoin} from 'rxjs/observable/forkJoin';
import {map} from 'rxjs/operators';
homeCards$= forkJoin(latestCards$,featuredCards$).pipe(
map(([latest,feature]=>[latest,...feature])
);
This has one limitation: waits for both requests to be completed to emit the first value, which is the complete list.
Naive approach 2:
import {combineLatest} from 'rxjs/observable/combineLatest';
import {map} from 'rxjs/operators';
homeCards$= combineLatest(latestCards$,featuredCards$).pipe(
map(([latest,feature]=>[latest,...feature])
);
Same limitation as before, only that it waits for both streams to emit at least once. Because these are http observables, they only emit once (response) and then complete. So its the same.
A better approach:
Assuming that the latestCard$ request takes less time to respond, use it as first result while fetching the rest of the data on the background.
import {merge} from 'rxjs/observable/merge';
import {of} from 'rxjs/observable/of';
import {mergeMap, map}from'rxjs/operators';
homeCards$= latestCards$.mergeMap(latest => {
const fullResult$ = featuredCards$.map(featured => [latest,...featured]);
return merge(of([latest]), fullResult$);
});
Upvotes: 2
Reputation: 2454
There are many ways to solve this, one would be this:
Observable
.combineLatest(latestCards$, featuredCards$) // return an array of responses
.map(([lastestCard, featuredCards]) => [lastestCard, ...featuredCards])
.subscribe(// do your stuff)
Here's an example in jsfiddle: http://jsfiddle.net/foxfghhn/
Upvotes: 2