Shahar Shokrani
Shahar Shokrani

Reputation: 8762

How to prevent a resolver from calling the same multiple http get requests

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]}
];

Upvotes: 1

Views: 1507

Answers (1)

Shahar Shokrani
Shahar Shokrani

Reputation: 8762

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();
        });
}

Upvotes: 1

Related Questions