【问题标题】:how to make HTTP call only once on component creation如何在组件创建时只进行一次 HTTP 调用
【发布时间】:2019-05-25 13:03:26
【问题描述】:

我正在通过 Angular 6 从 Web api 检索数据。

我使用组件构造函数中调用的 fetch 函数创建了一个服务,该函数将在同一页面上多次实例化。

我的问题是每次实例化我的组件时都会调用该服务。

例如我的代码如下:

服务:

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,但我收到了针对组件的每个实例的 Web api 请求。

【问题讨论】:

  • 如果您想重新提出您的问题,您希望getArticles() 只被调用一次。您实际上只有一个服务实例。只需调用最相关的组件中的方法,并通过Input/services 将其传递给其他人

标签: angular service


【解决方案1】:

通过声明你的组件

@Injectable({
  providedIn: 'root'
})

您保证它将是您的服务的一个实例,问题在于每次调用 subscribe 时都会执行整个观察者链(包括 get)。你必须这样做:

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

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

它将为每个订阅汇出价值。

【讨论】:

    【解决方案2】:

    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()来获取缓存的数据,并且你可以在你的组件构造函数中初始化数据(因为你的服务是一个单例,如果你试图用已经缓存的数据调用它,服务将简单地忽略请求) .

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-14
      • 2019-12-17
      • 1970-01-01
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-26
      相关资源
      最近更新 更多