1

I'll try to explain as well as I can, this is my first Ionic app ever.

My goal is to create a simple dashboard with some categories fetched from a JSON file, calling the Cordova HTTP native service. When one of the categories in the dashboard is clicked, it should load another dashboard with categories based on the particular ID param I sent through the [routerLink] directive.

It works as expected, but when I tap the "back" button and I go back to the main dashboard, if I click the same category ngOnInit() method is triggered and the http service fetches the data again.

I'd like to click on one category and call the http service only the first time, if that particular category data are not fetched yet, while simply displaying that data when this category is clicked the second time.

I've tried to check for this.category_sources but probably the component is destroyed everytime I tap the "back" button and data are lost.

  ngOnInit() {
    this.retrieveID();
    console.log("OnInit");
    this.presentLoading();
    this.CategoryCtrl();
  }

  retrieveID() {
    this.sub = this.route.params.subscribe(params => {
      this.id = +params['id'];
    });
  }

  CategoryCtrl() {
    if (this.category_sources) {
      console.log("Data already existing");
      this.stopLoading();
    } else {
    this.serverService.getReviewsCategory(this.id)
    .subscribe((data) => {
      this.fetched = true;
      this.category_sources = data['reviews'];
      this.info = data['info'];
      this.banner = data['banner'];
      this.fetched = true;
      this.stopLoading();
    });
  }
}

  backClicked() {
    console.log("Back clicked");
    this.location.back();
  }

  async presentLoading() {
    const loadingController = this.loadingController;

    const loadingElement = await loadingController.create({
      spinner: 'crescent',
    });
    return await loadingElement.present()
  }

  async stopLoading() {
    return await this.loadingController.dismiss();
  }

}
Federico
  • 415
  • 1
  • 3
  • 15
  • 4
    move the code for sending/reciving data into service, inside service cache the data and use this cached data instead of sending new request to web server (https://blog.thoughtram.io/angular/2018/03/05/advanced-caching-with-rxjs.html). Another way would be to use http interceptor. – alt255 Mar 24 '19 at 11:51
  • 1
    I have answer about the same topic here https://stackoverflow.com/questions/55136593/how-to-perform-caching-http-get-request-in-angular-5/55139368#55139368 – Muhammed Albarmavi Mar 24 '19 at 13:30
  • Thanks everyone! @malbarmawi that cache service worked like a charm!! I only have a last question...I have a LoadingController, I used to presentLoading() in the ngOnInit method and stopLoading() in the subscribe body. It works when it fetches data from Http service (the first time), but when data are from the cache the spinner doesn't stop its execution..the subscribe body is not executed in that case so spinner keeps loading and never dismiss.. I'd like to load the spinner only during the first http call and never show it again but ngOnInit is always executed and presentLoading () with it – Federico Mar 24 '19 at 21:16
  • @Federico I have add an answer base on your case , you don't need to check if the data is cached it will handle in the server service class this – Muhammed Albarmavi Mar 25 '19 at 13:55
  • I followed everything you wrote and it works, the "Back" button works too, but if I click on "Home" in my tabs a new instance is created so the service is called again and even if data are from cache it takes a long time to complete the request. I don't have connection issues so I don't understand where could be the problem... – Federico Mar 27 '19 at 08:41
  • @Federico the servicemust be a global service and this in momery so if you close the app the caching will be gone I can update the service to localstorage if you want to save the caching in case the app close – Muhammed Albarmavi Mar 28 '19 at 02:32

2 Answers2

1

I have idea, you can using: (set,get) data after click success, save localStorage let data = localStorage.setItem('categories'); let data = localStorage.getItem('categories');

//FRONT-END ANGULA

categories:any={}

Constructor(){
  //check categories localStorage
  let dataCatogories = localStorage.getItem('categories');
  if(dataCatogories.length>0){
  
    //You can handle it here 
    this.categories = dataCategories;
  }

}


//CLick categories
getAllCatogories = ()=>{
  this.http.get('APP_URL').subscribe(item=>{
   localStorage.setItem("categories",item);
  }

}
skipperhoa
  • 431
  • 3
  • 7
1

You can create a global service to handle the caching this without local storage and just save the data in memory (object) so when the app close the data will gone

CashingService

@Injectable({ providedIn: "root"})
export class CashingService {

  private __cach = {}
  isCashed(url: string) {
    return this.__cach[url];
  }

  getData(url: string) {
    return this.__cach[url]
  }

  setData(url) {
    return (data) => {
      if (data && (data instanceof Error) === false)
        this.__cach[url] = data
    };

  }

  reset() {
    this.__cach = {};
  }
}

Implement the service

@Injectable()
export class ServerService {

  constructor(private http: HttpClient , private _c:CachingService ) { }

  public getReviewsCategory(url: any): Observable<any> {

    if (this._c.isCashed(url)){
     return of(this._c.getData(url));
    } else {
    return this.http.get(url)
      .pipe(
       tab(this._c.setData(url)),
       catchError(this.handleError('apiGetRequest'))
      );
    }

  }
}

get the data from the service

Component ✨

  ngOnInit() {
    this.retrieveID();
    console.log("OnInit");
    this.presentLoading();
    this.CategoryCtrl();
  }

  CategoryCtrl() {

    this.serverService.getReviewsCategory(this.id)
    .subscribe((data) => {
      this.category_sources = data['reviews'];
      this.info = data['info'];
      this.banner = data['banner'];
      this.fetched = true;
      this.stopLoading(); // stop the spinner
    });
  }
}

You can look to the answer about diffrent way like rxjs to handle chaching How to perform caching http get request in angular 5?

Muhammed Albarmavi
  • 23,240
  • 8
  • 66
  • 91