When one observable runs it is depedent on data which comes from another obseravble and I can't work out how to hanlde this dependency correctly.
One observable gets data from Firebase and by subscribing it creates a simple number array called novelsRead: Array
The other observable gets a response from an api and by subscribing it is meant to filter out all the records who's ids are present in novelsRead[].
The issue is, when a response comes from the api, novelsRead[] is still empty because Firebase hasn't responded yet so nothing will be filtered from the api response.
Code below:
export class HomePage {
currentnovels: any;
novels: any;
unreadnovels: any;
nextnovels: any;
novel: any;
resultsPageNumber: number = 1;
novelFullPosterPath: any;
novelsread: Array<number> = [];
private basePosterUrlMedium = 'http://image.novels.org/t/p/w500';
private basePosterUrlSmall = 'http://image.novels.org/t/p/w185';
constructor(private http: Http,
private novelsApi: NovelsApiService,
private dataService: DataService,
) {
//this takes data from Firebase and pushes it to simple array of ids (numbers)
this.dataService.list('novels-read')
.subscribe(data => {
data.map(results => {
this.novelsread.push(results.novelsId);
})
})
}
ngAfterViewInit() {
this.novelsApi.getnovelsByPage(this.resultsPageNumber)
.subscribe(data => {
this.novels = data.results;
this.novels.map(data => {
data.full_poster_path = this.basePosterUrlMedium + data.poster_path;
return data;
})
.filter(data => {
let found = this.novelsread.indexOf(data.id);
//It seems when the api responds, this.novelsRead is still empty [] because Firebase has not responded yet
console.log("this novelsread[0] is ", this.novelsread[0]);
console.log("data.id found is ", found);
return data;
})
})
}
I am looking for the cleanest solution whether that's using events, or observable chains or any other suggestions like moving functions from the constructor to ngAfterViewInit and vice versa.
I did look at code examples for combining observables using combineLatest but found the syntax very convoluted and wondered if there is a cleaner way of achiveing what I need, even if that involves waiting for events.
An observable produces values over time. An array is created as a static set of values. In a sense, observables are asynchronous where arrays are synchronous. In the following examples, → implies asynchronous value delivery.
The subscriber function defines how to obtain or generate values or messages to be published. To execute the observable you have created and begin receiving notifications, you call its subscribe() method, passing an observer. This is a JavaScript object that defines the handlers for the notifications you receive.
A common misconception in Angular development is regarding whether observables are synchronous or asynchronous. A lot of (even experienced Angular developers) think that observables are async, but the truth is that they can be… Both synchronous and asynchronous.
Observable is important because it helps to manage asynchronous data (such as data coming from a back-end server). So we can think of Observable as an array where items arrive asynchronously over time. With Observable we need a method in our code that will subscribe to this observable.
Using forkJoin
should help you.
It allows to handle result only when both requests complete:
https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/forkjoin.md
OR if your 2nd request depends on 1st response - use switchMap
const request1$ = Rx.Observable.of('response1').delay(2000);
const request2$ = Rx.Observable.of('response2').delay(100);
Rx.Observable.forkJoin(request1$, request2$)
.subscribe(res => console.log(`forkJoin: ${res}`));
request1$.switchMap(res1 => {
console.log(`switchMap: ${res1}`);
return request2$;
}).subscribe(res2 => console.log(`switchMap: ${res2}`));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.3.0/Rx.min.js"></script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With