I wanted to cache the api calls for different cities. The api's are mentioned in bankhttp.service.ts
Included interceptor in my-interceptor.service.ts and a reqCache.service.ts to cache the calls.
home.component.ts is used to process the api that contains city as Mumbai.
included the below code in providers array of app.module.ts
What's the correct procedure to cache the api calls so that no request are made for the same endpoints again and again providers: [BankhttpService, RequestCache, { provide: HTTP_INTERCEPTORS, useClass: CachingInterceptor, multi: true } ]
</my-interceptor.service.ts import { Injectable } from '@angular/core'; import { HttpEvent, HttpRequest, HttpResponse, HttpInterceptor, HttpHandler } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; import { startWith, tap } from 'rxjs/operators'; import 'rxjs/add/observable/of'; import { RequestCache } from './requestCache.service'; @Injectable() export class CachingInterceptor implements HttpInterceptor { constructor(private cache: RequestCache) {} intercept(req: HttpRequest<any>, next: HttpHandler) { const cachedResponse = this.cache.get(req); return cachedResponse ? Observable.of(cachedResponse) : this.sendRequest(req, next, this.cache); } sendRequest( req: HttpRequest<any>, next: HttpHandler, cache: RequestCache): Observable<HttpEvent<any>> { return next.handle(req).pipe( tap(event => { if (event instanceof HttpResponse) { cache.put(req, event); } }) ); } } /> </requestCache.service.ts import { Injectable } from '@angular/core'; import { HttpRequest, HttpResponse } from '@angular/common/http'; const maxAge = 30000; @Injectable() export class RequestCache { cache = new Map(); get(req: HttpRequest<any>): HttpResponse<any> | undefined { const url = req.urlWithParams; const cached = this.cache.get(url); if (!cached) { return undefined; } const isExpired = cached.lastRead < (Date.now() - maxAge); const expired = isExpired ? 'expired ' : ''; return cached.response; } put(req: HttpRequest<any>, response: HttpResponse<any>): void { const url = req.url; const entry = { url, response, lastRead: Date.now() }; this.cache.set(url, entry); const expired = Date.now() - maxAge; this.cache.forEach(expiredEntry => { if (expiredEntry.lastRead < expired) { this.cache.delete(expiredEntry.url); } }); } } /> </bankhttp.service.ts import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders, HttpClientModule } from '@angular/common/http'; import { HttpErrorResponse, HttpParams } from '@angular/common/http'; import { Observable } from 'rxjs/Observable' import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/do'; @Injectable({ providedIn: 'root' }) export class BankhttpService { public a1 = []; private baseUrl = "https://vast-shore-74260.herokuapp.com/banks"; public city1 = "BANGALORE" public city2 = "MUMBAI" public city3 = "DELHI" public city4 = "CHENNAI" public city5 = "HYDERABAD" constructor(private _http: HttpClient) { console.log('Bank http service called'); } private handleError(err: HttpErrorResponse) { console.log('Handle http error'); console.log(err.message); return Observable.throw(err.message); } public getBangaloreBranches(): Observable<any> { let myResponse = this._http.get(this.baseUrl + '?city=' + this.city1); //console.log(myResponse); return myResponse; } public getMumbaiBranches(): Observable<any> { let myResponse = this._http.get(this.baseUrl + '?city=' + this.city2); //console.log(myResponse); return myResponse; } public getDelhiBranches(): Observable<any> { let myResponse = this._http.get(this.baseUrl + '?city=' + this.city3); //console.log(myResponse); return myResponse; } public getChennaiBranches(): Observable<any> { let myResponse = this._http.get(this.baseUrl + '?city=' + this.city4); //console.log(myResponse); return myResponse; } public getHyderabadBranches(): Observable<any> { let myResponse = this._http.get(this.baseUrl + '?city=' + this.city5); //console.log(myResponse); return myResponse; } } /> <home.component.ts import { Component, OnInit, Inject, ViewChild, ElementRef } from '@angular/core'; /*importing mat-table components*/ import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { MatSort, MatTableDataSource, MatPaginator, MatCheckboxModule } from '@angular/material'; /*importing services*/ import { BankhttpService } from '../bankhttp.service'; /*importing selection model to provide checkboxes to the list of banks*/ import { SelectionModel } from '@angular/cdk/collections'; /*interface for the json data present in the api*/ export interface User { ifsc: string; bank_id: string; branch: string; address: string; city: string, district: string, state: string, bank_name: string } @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.css'], styles: [ ` table { width: 100%; } th.mat-sort-header-sorted { color: black; } ` ] }) export class HomeComponent implements OnInit { public value = []; selectedRowIndex: any; displayedColumns: string[] = ['favorite', 'bank_name', 'ifsc', 'bank_id', 'branch', 'city', 'district', 'state']; dataSource; user; data users: User[]; selection = new SelectionModel<User>(true, []); @ViewChild('button') button: ElementRef; @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; /** Whether the number of selected elements matches the total number of rows. */ isAllSelected() { const numSelected = this.selection.selected.length; const numRows = this.dataSource.length; return numSelected === numRows; } /** Selects all rows if they are not all selected; otherwise clear selection. */ masterToggle() { this.isAllSelected() ? this.selection.clear() : this.dataSource.forEach(row => this.selection.select(row)); } /** The label for the checkbox on the passed row */ checkboxLabel(row?: User): string { if (!row) { return `${this.isAllSelected() ? 'select' : 'deselect'} all`; } return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.ifsc + 1}`; } constructor(public bankHttpService: BankhttpService, public dialog: MatDialog) { console.log('Home component constructor is called'); if (localStorage.getItem('fav') === '' || localStorage.getItem('fav') === null) { } else { this.value = JSON.parse(localStorage.getItem('fav')); console.log('from localStorage', this.value) } } ngOnInit() { console.log('Home component onIniti called'); /*subscribing to the services*/ this.bankHttpService.getMumbaiBranches() .subscribe((users: User[]) => { this.users = users; this.dataSource = new MatTableDataSource(users); this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; }); } /*filter the list of banks*/ applyFilter(filterValue: string) { filterValue = filterValue.trim(); // Remove whitespace filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches this.dataSource.filter = filterValue; } toggle = true; status = 'Enable'; selectedUser: any; /*function triggered when click event is performed on the checkboxes adjacent to the bank list*/ activeSkill(element: any) { let checkExists: boolean = false; console.log(this.value) console.log(this.value.length) console.log(element.ifsc) for (let i = 0; i < this.value.length; i++) { if (element.ifsc === this.value[i].ifsc) { checkExists = true; console.log(checkExists) } } if (checkExists === false) { console.log(checkExists) this.value.push(element); } /*storing the data selected during click event inside the local storage of the browser*/ localStorage.setItem('fav', JSON.stringify(this.value)); } } />