как сделать HTTP-вызов только один раз при создании компонента - PullRequest
0 голосов
/ 27 декабря 2018

Я получаю данные из веб-API через угловую 6.

Я создал сервис с функцией выборки, которая вызывается в конструкторе компонентов, который будет несколько раз создаваться на одной и той же странице.

Моя проблема в том, что служба вызывается каждый раз, когда создается экземпляр моего компонента.

Например, мой код следующий:

Служба:

import { Injectable } from '@angular/core';
import { Article } from '../../Classes/article'
import { Observable } from 'rxjs';
import { MessageService } from '../../Services/message/message.service'
import { HttpClient } from '@angular/common/http'


@Injectable({
  providedIn: 'root'
})
export class ArticleService {

  Values:  Observable<Article[]> ;


  constructor(private messageService: MessageService, private http : HttpClient) 
  { 
 this.buildArticles()
  }

private articlesUrl = 'http://localhost:63138/v/Article'

private buildArticles():  void {
    this.Values =  this.http.get<Article[]>(this.articlesUrl)
}

getArticles() : Observable<Article[]> {
return this.Values
  }
}

Мой компонент:

import { Component,OnInit, Input } from '@angular/core';
import { ArticleService } from 'src/app/Services/article/article.service';
import { Article } from 'src/app/Classes/Article'

@Component({
  selector: 'app-article',
  templateUrl: './article.component.html',
  styleUrls: ['./article.component.scss'],
})

export class ArticleComponent implements OnInit {

  @Input() artId  :number;


  constructor( private articleService : ArticleService) { 
    articleService.getArticles().subscribe(x=> this.articles = x);
   }
  articles : Article[];
  ngOnInit(): void {
  }
}

с компонентом html:

<mat-form-field>
  <mat-select [(ngModel)]="artId" >
    <mat-option *ngFor="let art of articles" [value]="art.Id"> 
 {{art.Libelle1}}</mat-option>
  </mat-select>
</mat-form-field>

Теперь в моем приложении я бы хотел, чтобы метод выборки службы вызывался один раз, и каждый раз повторно использовал данныеЯ создаю новый компонент.

В app.module.ts я помещаю providers: [ArticleService] в @NgModule, но я получаю запрос к моему веб-API для каждого экземпляра компонента.

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

Angular создает компоненты по запросу.

В вашем случае при каждом создании компонента вы делаете HTTP-вызов, используя сервисный метод для извлечения ваших данных.

Проблема не в экземплярах службы (или даже в вашем компоненте), а в выбранном вами дизайне, который не соответствует вашему случаю.

Вам нужно что-то вроде кеширования.Чтобы реализовать это, вы можете использовать предметы:

private _cachedData: Subject<any>;
public data = this._cachedData.asObservable();

refreshData() {
  this.http.get(...).subscribe(res => this._cachedData.next(res));
}

initializeData() {
  if (!this._cachedData) {
    this._cachedData = ,new Subject();
    this.refreshData();
  }
}

Это очень просто, но это должно сработать.Теперь вы можете просто использовать myService.data.subscribe() для получения кэшированных данных и инициализировать данные в конструкторе вашего компонента (поскольку ваш сервис одноэлементный, если вы попытаетесь вызвать его с уже кэшированными данными, сервис просто проигнорирует запрос),

0 голосов
/ 27 декабря 2018

Объявляя ваш компонент

@Injectable({
  providedIn: 'root'
})

, вы гарантируете, что это будет один экземпляр вашего сервиса, проблема в том, что при каждом вызове подписки выполняется вся цепочка наблюдателей (включая get),Вы должны сделать что-то вроде этого:

import { publishReplay, refCount } from 'rxjs/operators';    

return this.http.get<Article[]>(this.articlesUrl)
      .pipe(
       publishReplay(),
       refCount())

он будет переводить значение для каждой подписки.

...