1

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]}
];
3
  • You'd have to add caching somewhere, probably in FooService so all consumers benefit from it. Commented Jul 7, 2020 at 10:33
  • You can use rxjs shareReplay() operator in pipe() of http.get() Commented Jul 7, 2020 at 10:34
  • Hey guys, thanks for the tips, I've posted an answer of my own by your comments Commented Jul 9, 2020 at 18:30

1 Answer 1

1

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();
        });
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.