0

I am working on angular 6 project, where I need to call get API service in multiple components, so what is the best solution to avoid calling the same API multiple times in different components and only data can be accessible in required components, please provide with an example thank you

vinuta
  • 423
  • 9
  • 29
  • 2
    Welcome to stackoverflow. Please, show us a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) and you'll get help – gehbiszumeis Oct 11 '18 at 06:05
  • 1
    Have you tried anything yet? Do you have any idea how to do that? Have you studied anything related to this? Any research you did related to this? – Exterminator Oct 11 '18 at 06:09
  • https://stackoverflow.com/a/52717933/5695162 – Vikas Oct 11 '18 at 06:31
  • you can implement some caching in your service (if it's not already loaded, load it, then deliver what's loaded) – Pac0 Oct 11 '18 at 11:09

3 Answers3

1

You can use ngrx/store to store the data received from the api call and use it in different components.

Akash Jain
  • 39
  • 2
0

You can take the advantage for HTTP_INTERCEPTORS and Caching mechanism to avoid multiple API calls.

cache.interceptor.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 './request-cache.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);
        }
      })
    );
  }
}

cache.request.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);
      }
    });
  }
}

setup interceptor in app.module.ts

import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { RequestCache } from './request-cache.service';
import { CachingInterceptor } from './caching-interceptor.service';

// ...

providers: [
    RequestCache,
    { provide: HTTP_INTERCEPTORS, useClass: CachingInterceptor, multi: true }
  ],

// ...
Community
  • 1
  • 1
Sunil Singh
  • 11,001
  • 2
  • 27
  • 48
0

You can use rxjs shareReplay. Something like

let data$ = this.http.get(...url...).pipe(
shareReplay()
);

Now every subscriber to the data observable will get the data in a single http call

let call1 = data$.subsribe();
let call2 = data$.subscribe();
Suryan
  • 701
  • 7
  • 17