0

I am using Angular 5.0.0.

I have a drop-down menu which is populated by data from a remote server. This drop-down data is part of a component which is used multiple times on a page. Therefore, every time the component is used, the data is being retrieved from the server. I want it to retrieve the data one time, cache it, then use the cached value for each instance after that.

I followed the general pattern from the Angular 5 documentation and the specific detail from this StackOverflow answer. Here is my interceptor:

@Injectable()
export class CachingInterceptor implements HttpInterceptor {
  private cache = {};

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (req.method !== 'GET') {
      return next.handle(req);
    }

    console.log("Checking cache for "+req.urlWithParams);
    const cachedResponse = this.cache[req.urlWithParams] || null;
    if (cachedResponse) {
        console.log("Returning cached version of "+req.urlWithParams);
        return Observable.of(cachedResponse);
    }

    return next.handle(req).do(event => {
        if (event instanceof HttpResponse) {
            console.log("Setting the cache value for "+req.urlWithParams);
            this.cache[req.urlWithParams] = event;
        }
    });
  }
}

The interceptor has been injected properly it would appear, but here is what happens in the console:

Checking cache for api/proposal-statuses
Checking cache for api/proposal-statuses
Checking cache for api/proposal-statuses
Checking cache for api/proposal-statuses
...
GET XHR http://localhost:4200/api/proposal-statuses
GET XHR http://localhost:4200/api/proposal-statuses
GET XHR http://localhost:4200/api/proposal-statuses
GET XHR http://localhost:4200/api/proposal-statuses
...
Setting the cache value for api/proposal-statuses
Setting the cache value for api/proposal-statuses
Setting the cache value for api/proposal-statuses
Setting the cache value for api/proposal-statuses
...

What I would expect to see would be:

Checking cache for api/proposal-statuses
GET XHR http://localhost:4200/api/proposal-statuses
Setting the cache value for api/proposal-statuses
Returning cached version of api/proposal-statuses
Returning cached version of api/proposal-statuses
Returning cached version of api/proposal-statuses
Returning cached version of api/proposal-statuses
...

My service to retrieve the data is:

import { Injectable } from '@angular/core';
import { ProposalStatus } from './proposal-status';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class ProposalStatusService {
  private serviceUrl = 'api/proposal-statuses';  // URL to web api

  constructor(private http: HttpClient) { }

  getAllProposalStatuses(): Observable<ProposalStatus[]> {
    return this.http.get<ProposalStatus[]>(this.serviceUrl);
  }
}

Then in the component this is how the service is called:

@Component({
  selector: 'proposal',
  templateUrl: './proposal.component.html',
  styleUrls: ['./proposal.component.scss']
})
export class ProposalComponent implements OnInit {
    ...

    statusdata: Observable<ProposalStatus[]>;

    constructor(private proposalStatusService: ProposalStatusService,
                ...) { }

    ngOnInit() {
        this.statusdata = this.proposalStatusService.getAllProposalStatuses();
        ...
    }
}

Why am I not getting the results I expect? This behavior is happening to everything, not just this particular service. Any insight would be helpful. Thanks!

8
  • You're making four requests in parallel, none of them has completed (and therefore been cached) until all of them have started. That's exactly what the logs are showing you. Commented Dec 5, 2017 at 18:04
  • @jonrsharpe So how do I make it so that the requests are not parallel? Commented Dec 5, 2017 at 18:08
  • It's not clear from what you've posted why you are making the same request four times simultaneously, maybe look into that? Commented Dec 5, 2017 at 18:09
  • @jonrsharpe I am displaying a list of proposals, so the ProposalComponent is used multiple times. Each time the ProposalComponent is used, it tries to get the ProposalStatus data. Commented Dec 5, 2017 at 18:12
  • But as far as the request is saying it's... showing the same proposal four times? It seems like you're trying to use caching to fix a more fundamental problem. Why not get the statuses once in the parent and pass it to the child components from there, for example? If you really must cache, you'll have to figure out how to deal with a request potentially being in flight but not yet in the cache. Commented Dec 5, 2017 at 18:16

0

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.