Reputation: 4519
I have a few services that are working with the observable principle. I want to get the results of 2 services inside a resolver to use at my page. But the result inside the page is just a empty data object. I have also tried first()
instead of take(1)
, but no difference there.
My resolver:
@Injectable({
providedIn: 'root'
})
export class CompanyResolver implements Resolve<any> {
constructor(private companyResolver: CompanyService, private countryService: CountryService, private genderService: GenderService) { }
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) {
return forkJoin({
countries: this.countryService.getCountries().pipe(take(1)),
genders: this.genderService.getGenders().pipe(take(1)),
});
}
}
My page:
export class SettingsCompanyOverviewComponent implements OnInit {
constructor(
public countryService: CountryService,
private route: ActivatedRoute
) {
console.log(this.route.snapshot);
}
ngOnInit(): void {
}
}
Service:
export class CountryService {
private countryObserver$: BehaviorSubject<CountryInterface[]> = new BehaviorSubject([]);
constructor(
private apiService: ApiService
) {
this.getData();
}
getCountries(): Observable<GenderInterface[]> {
return this.countryObserver$.asObservable();
}
private getData(): void {
this.apiService.get<CountryInterface[]>(ApiRoutes.getCountries, null).then(res => {
this.countryObserver$.next(res);
});
}
}
I don't get what is going wrong as I really expect data from both services.
Edit: It seems that the first data from the observable is empty, after that I get the expected results. I thought that BehaviorSubject
gives the last result back?
Upvotes: 1
Views: 87
Reputation: 73357
As established in comment, BehaviorSubject emits the initial value in the resolver, because it takes some time for the http-request to complete, but by then, when new value would be emitted, the resolver has already done its job.
Looks to me that you wouldn't need the behaviorSubject as a middleman? You could assign it directly to an observable. If you need to share same data, you can use shareReplay
which just emits the value without making a http request. So something like this for the country service:
export class CountryService {
constructor(
private apiService: ApiService
) { }
countries$ = this.getData().pipe(shareReplay());
private getData(): Observable<CountryInterface[]> {
return this.apiService.get<CountryInterface[]>(ApiRoutes.getCountries, null)
}
}
Then in your resolver, just listen to countries$
instead of your BehaviorSubject.
return forkJoin({
countries: this.countryService.countries$.pipe(take(1)),
//....
});
You can apply the same for your other service like I did above for the country service.
Upvotes: 1