Reputation: 130
I started to play around with Angular 6 and Firebase. I wanted to use Hacker News API for displaying feeds (things).
I wanted to return an observable of an array of Thing class. Firstly I need an array of feed IDs, so I make a call to Firebase to fetch these. Then I wanted to fetch the feeds for each ID I already have, and return it as a single observable of an array of feeds.
What I have so far is the code like this:
getThings(limit: number): Observable<any> {
return this.db.list('/v0/beststories', ref => ref.limitToFirst(limit).orderByKey())
.valueChanges() // returns an Observable of IDs
.pipe(
flatMap(itemIds => {
if (itemIds.length > 0) {
let sources = itemIds.map(itemId => defer(() => {
let pathOrRef = '/v0/item/' + itemId;
return this.db.object(pathOrRef).valueChanges();
}));
// sources are the array of Observables
return forkJoin(sources);
} else {
return Observable.create([]);
}
})
);
}
I thought that flatMapping from the array would be the solution, but I get You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable
.
I tried to do this in similar way as it's in RxJs Array of Observable to Array , but I don't know where I made a mistake.
The error is thrown after invoking subscribe on the returned Observable:
this.hackerNewsService.getThings(20).subscribe(console.log);
The similar situation I reproduce in the following snippet: https://stackblitz.com/edit/angular-8qtokd?file=src%2Fapp%2Fapp.component.ts
Upvotes: 4
Views: 5671
Reputation: 18523
Try using switchMap
and combineLatest
. e.g.
import {combineLatest, Observable} from 'rxjs';
import {map, switchMap} from 'rxjs/operators';
function getThings(limit: number): Observable<any> {
return this.db.list('/v0/beststories', ref => ref.limitToFirst(limit).orderByKey())
.valueChanges() // returns an Observable of IDs
.pipe(
switchMap(itemIds => {
if (itemIds.length > 0) {
let sources = itemIds.map(itemId => {
let pathOrRef = '/v0/item/' + itemId;
return this.db.object(pathOrRef).valueChanges();
});
// sources are the array of Observables
return combineLatest(sources);
} else {
return Observable.create([]);
}
})
);
}
Upvotes: 7