2

I have a very simple API call when clicking on minister router link. It displays some data when minister page is open. But I see whenever I came back to that page either from the homepage or any other page the API keeps loading again.

duplicate api calls

minister.component.ts

import { Component, OnInit } from '@angular/core';
import { ApiReadService } from "../apiReadService.service";

interface mydata{
  allMinisters: Object
}

@Component({
  selector: 'app-ministers',
  templateUrl: './ministers.component.html',
  styleUrls: ['./ministers.component.scss']
})
export class MinistersComponent implements OnInit {

  allData:Object = [];

  constructor(private apiRead: ApiReadService) {

  }
  ngOnInit(){
  this.apiRead.getData().subscribe(data=>{
            this.allData  = data.allMinisters;
    }); 
  }
}

apiReadSerivce.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/Http';

@Injectable({
  providedIn: 'root'
})

export class ApiReadService {
    constructor(private http: HttpClient) { }

    getData(){
        return this.http.get('http://localhost:8081/allMinisters')
    }
}
4
  • there can be 2 first for the options and second actual call, clear your console and then route to that page and check how many requests are going. Commented Dec 31, 2018 at 6:27
  • only 1 at a time. The api loads every time I come back to that page Commented Dec 31, 2018 at 6:28
  • ngOnInit is called every time the component is created... which is every time you view the page. As you are calling this.apiRead.getData in ngOnInit you need a way to cache the data, which Simon_Weaver has shown below... although there are many ways to cache data client side. Commented Dec 31, 2018 at 6:35
  • You can use this very efficiently - npmjs.com/package/ngx-cacheable Commented Dec 31, 2018 at 9:47

1 Answer 1

7

The simplest way - if you only ever want the data to load once is something like this:

import { shareReplay } from 'rxjs/operators';

export class ApiReadService {
   constructor(private http: HttpClient) { }

   ministers$ = this.http.get('http://localhost:8081/allMinisters')
                         .pipe(shareReplay(1))

   getData() {
      return this.ministers$;
   }
} 

Once the results have been returned once it will get 'cached' by the shareReplay(1) and that same value returned each time.

Sign up to request clarification or add additional context in comments.

7 Comments

If you're new to Angular I strongly recommend reading as much as you can about RxJS. Try to find articles specifically related to Angular, because they'll be more useful - or just stackoverflow questions. Understanding RxJS really helps take advantage of Angular's potential like nothing else.
Thanks for your tip. will start angular tutorial. Also do you mind telling me if I need to import something fro shareReplay(1)
Thanks your updated answer solve my problem. But if I update my api during the period, does it show updated answer?
you mean if you add a new minister - no it wouldn't. You'd need to decide when to refresh this - and that in itself can get surprisingly complicated. But if you only want to load it once this would work.
Not mandatory, it's just a convention followed for naming Observables
|

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.