Как хранить данные, полученные от API, в сервисе angular и избежать нескольких вызовов API? - PullRequest
0 голосов
/ 10 мая 2019

Я использую службу angular (v6) для извлечения данных из бэкэнда и сохранения в переменной.Я хочу вызвать API только один раз и обслуживать данные всякий раз, когда это требуется для различных компонентов.

Проблема в том, что я вызываю функцию getPlans () в службе из разных компонентов для получения данных, и для каждого вызова я вижу вызов API в закладке сети браузера.

Как избежать вызова каждый раз, когда я вызываю функцию getPlans () и обслуживаю данные, вызывающие API один раз и сохраняющие их в переменной?

export class PlansService {
  private plansData:any = {};

  constructor(private httpCallService: HttpCallService, private http: HttpClient) { 

    this.plansData = this.httpCallService.getHttpResponse("GET_PLANS");

  }
  getPlans(): Observable<any>{
    return this.plansData;
   }

}

Ответы [ 2 ]

0 голосов
/ 10 мая 2019

Это можно сделать с помощью shareReplay () RxJ. Согласно История изменений ,

shareReplay возвращает наблюдаемое, являющееся источником многоадресной передачи ReplaySubject. Эта тема воспроизведения по ошибке возвращается из источник, но не по завершении источника. Это делает shareReplay идеально подходит для обработки таких вещей, как кэширование результатов AJAX, так как retryable. Это повторное поведение, однако, отличается от доли в том, что он не будет повторять наблюдаемый источник, скорее он будет повторять исходные наблюдаемые значения.

Что делает пользователя shareReplay() идеальным для вашего варианта использования.

Не забудьте также импортировать shareReplay () на ваш сервис.

import { shareReplay } from 'rxjs/operators';
.
.

export class PlansService {
  private plansData: Observable<any>;

  constructor(private httpCallService: HttpCallService, private http: HttpClient) { 

    this.plansData = this.httpCallService.getHttpResponse("GET_PLANS")
      .pipe(
        shareReplay()
      );

  }

  getPlans(): Observable<any>{
    return this.plansData;
   }

}

Затем вы можете вернуть наблюдаемое в компоненте, которому это требуется, и если вы посмотрите на вкладку сетевого запроса в инструменте Inspect Element, дополнительные HTTP-запросы не запускаются, поскольку наблюдаемое с кэшированными значениями возвращается каждый раз getPlans() называется.

0 голосов
/ 10 мая 2019

Вы можете использовать ReplaySubject или BehaviorSubject , чтобы заставить это работать, если вы используете ReplaySubject, вам нужно указать, сколько старых значений вы хотите сохранить, чтобы подписчики могли получить доступ позже, BehaviorSubject можетоставьте только последнее значение

 import { ReplaySubject } from 'rxjs';

 ....
 @Injectable()
 export class SharedService {
 plans$: Observable<Plan[]> = this.plansSubject.asObservable(); 
 private plansSubject = new ReplaySubject<Plan[]>(1);

 constructor(private http: HttpClient) { }
 getPlans(){
   this.http.get().subscribe(res => this.plansSubject.next(res.plans)); // get array of plans
 }
}

, и вы можете получить данные в своих компонентах следующим образом:

constructor(private sharedService: SharedService) { }

ngOnInit() {
 this.sharedService.getPlans(); // to get called only the first time to get data
 this.service.plans$.subscribe(...); // you have your data here without anu additional http call 
}

и, если вы хотите обновить данные, вы можете вызвать метод

this.sharedService.getPlans();

для BehaviorSubject это точно то же самое, здесь что изменится

plans$: Observable<Plan[]> = this.plansSubject.asObservable(); 
private plansSubject = new BehaviorSubject<Plan[]>;

вы можете подписаться внутри своего компонента, чтобы получить данные, или вы можете получить доступиспользуя BehaviorSubject.value

constructor(private sharedService: SharedService) { }

ngOnInit() {
 this.service.plans$.subscribe((plans) => console.log(plans));
 // or access the value directly
 console.log(this.service.plans$.value)    
}
...