My app has several routing re-directions that each on of them triggering the FooResolverService
, and each resolve invocation calls a FooService
's method of GetFoos
http get method (so my resource api is being requested multiple times with the same request).
How to allow only for the first invocation of the resolve
to actually call the resource api via the FooService
?
export class FooResolverService implements Resolve<FooModel[]> {
constructor(
private fooService: FooService
) {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
console.log("resolve");
return this.fooService.getFoos();
}
}
FooService
:
getFoos() : FooModel[] {
if (this.foos.length === 0) {
this._foosAPIService.fetchFoos().subscribe(foos =>
{
this.setFoos(foos);
});
}
else {
return this.foos;
}
}
setFoos(foos: FooModel[]) {
this.foos = foos;
}
FoosAPIService
fetchFoos() : Observable<FooModel[]> {
return this._httpClient
.get<FooModel[]>(
this._configService.resourceApiURI + 'foos/'
);
}
Routes
const routes: Routes = [
{ path: '', component: FoosComponent, children: children},
{ path: ':id', component: FoosComponent, children: children, resolve: [FoosResolverService]}
];
As the comments suggested, I've ended up caching the Observable
itself (instead of caching the results), with the help of shareReplay()
:
FoosAPIService
:
fetchFoos(filter: string) : Observable<EventFoo[]> {
if (this.fetchFoos$[filter]) {
return this.fetchFoos$[filter];
}
this.fetchFoos$[filter] = this._httpClient
.get<FooModel[]>(
this._configService.resourceApiURI + 'events/'
)
.pipe(
shareReplay({ bufferSize: 1, refCount: true })
);
return this.fetchFoos$[filter];
}
Service
:
fetchFoos(filter: string) : void {
this.foosSubscription = this._foosAPIService.fetchFoos(filter)
.subscribe(foos =>
{
this.setFoos(foos);
this.foosSubscription.unsubscribe();
});
}