I am building an application in Angular8 and rxjs6. I am working on separating out logic from one large component into a service.
I am using the combineLatest function to get the results of multiple observables. Then inside the body of combineLatest subscribe(=>{})
the results data is used to update multiple BehaviorSubjects.
The issue I am running into is that I need to make sure those BehaviorSubjects get the latest data first before moving onto the next statements in the component.
The combineLatest code works fine in the body of the component because I can put the rest of the logic inside the body of subscribe. However, I want to move the combineLatest logic to a service, therefore I need to be able to wait for the logic inside of subscribe() to be completed before moving onto the next statements in the component.
Other similar questions suggest the use of map() or returning an observable of(). However none of these solutions seem to work.
I am trying to return a wrapper function around combineLatest as an observable and then subscribe to that inside the component. However it is not working correctly.
Service
import { Observable, BehaviorSubject, combineLatest, throwError } from 'rxjs';
// Create a BehaviorSubject to track and share updates to People Options
peopleOptions: any = {};
peopleOptionsResponse = new BehaviorSubject(this.peopleOptions);
peopleOptionsObservable = this.peopleOptionsResponse.asObservable();
// Create a BehaviorSubject to track and share updates to Projects Options
projectsOptions: any = {};
projectsOptionsResponse = new BehaviorSubject(this.projectsOptions);
projectsOptionsObservable = this.projectsOptionsResponse.asObservable();
getSharedOptions(): Observable<any> {
// Combine results of multiple observables
return combineLatest([
// Get current value of Record Detail subject
this.getProjects().pipe(catchError(err => {
console.error(`getProjects failed ${err}`);
return throwError(err);
})),
this.getPeople().pipe(catchError(err => {
console.error(`getPeople failed ${err}`);
return throwError(err);
}))
]).subscribe(results => {
// Get projects select options
let projectsOptions = results[0];
// Update current value of Projects Options behavior subject to share with subscribers
this.projectsOptionsResponse.next(projectsOptions);
/* The logic in the component that uses the behavior subjects' data should execute after this is complete only */
});
}
Component
this.exampleService.getSharedOptions().subscribe(result => {
/* Component logic that uses the current data in the behavior subjects which were updated in the service's getSharedOptions combineLatest subscribe body */
});
Error message:
this.exampleService.getSharedOptions(...).subscribe is not a function
this.exampleService.getSharedOptions(...).subscribe is not a function
This is happening because getSharedOptions
is not returning an Observable, instead, it returns a Subscription
instance.
To fix the issue lets change your getShareOptions()
method like this:
getSharedOptions(): Observable<any> {
// Combine results of multiple observables
return combineLatest([
// Get current value of Record Detail subject
this.getProjects().pipe(catchError(err => {
console.error(`getProjects failed ${err}`);
return throwError(err);
})),
this.getPeople().pipe(catchError(err => {
console.error(`getPeople failed ${err}`);
return throwError(err);
}))
]).pipe(
tap(results => {
// Get projects select options
let projectsOptions = results[0];
this.projectsOptionsResponse.next(projectsOptions);
})
);
And then in component -
this.exampleService.getSharedOptions().subscribe(result => {
/* Component logic that uses the current data in the behavior subjects which were updated in the service's getSharedOptions combineLatest subscribe body */
});
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments