ค้นหาเว็บไซต์

typescript - สมัครสมาชิกการเรียกบริการเดียวกันโดยไม่เรียกบริการหลายครั้งใน Angular 7


ฉันมีส่วนประกอบสองส่วนที่ในเวลาเดียวกันสามารถมองเห็นได้ในมุมมองเดียวกัน ในเมธอด ngOnInit() ของพวกมัน ฉันสมัครสมาชิก (subscribe) กับ Observable เดียวกันจากบริการ ซึ่งส่งผลให้เกิดการเรียกเครือข่ายสองครั้งซึ่งไม่จำเป็น ฉันจะแบ่งปันการตอบกลับจากบริการให้กับผู้สมัครสมาชิกทั้งสองได้อย่างไรเพื่อให้เกิดการเรียกเครือข่ายเพียงครั้งเดียว?

รหัสเรียกใช้บริการของฉันคือ:

getDashboardViewModel (): Observable<DashboardViewModel> {
return this.get<DashboardViewModel>(Constants.DashboardApiUrl);

และวิธีที่ฉันได้สมัครมันในทั้งสองส่วนประกอบคือ:

ngOnInit() {
   this.dashboardService.getDashboardViewModel().subscribe(dashboardVM => this.dashboardViewModel = dashboardVM);
}

ฉันจะทำอย่างไรให้การเรียกเครือข่ายเกิดขึ้นเพียงครั้งเดียวและทั้งสองคอมโพเนนต์ได้รับข้อมูล ฉันกำลังใช้ Angular 7

คำตอบ #1

คุณสามารถทำอะไรบางอย่างแบบนี้ได้:

@Injectable()
export class Service{
  dashboardModel: ReplaySubject<Model> = new ReplaySubject<Model>'
  constructor(private _http: HttpClient) {
    this._http.get<Model>(url).subscribe((model: Model) => {
      this._dashboardModel.next(model);
    });
  }
}

และจากนั้นในการเรียก init ของคุณในคอมโพเนนต์ของคุณเพียงทำ:

this._service.dashboardModel.first().subscribe((model) => {});

ReplaySubject ช่วยให้สามารถดึงค่าล่าสุด n ค่า ที่ถูกส่งออกโดย observable ได้

คำตอบ #2

ถ้าการร้องขอข้อมูลสามารถถูกเรียกใช้งานผ่าน resolver จะทำให้เรื่องง่ายขึ้น อย่างไรก็ตามคุณสามารถทำตามคำตอบก่อนหน้าหนึ่งข้อ โดยใช้คอนเทนเนอร์สมาร์ทที่ครอบคอมโพเนนต์ของคุณซึ่งต้องใช้ข้อมูลนั้น คอนเทนเนอร์สมาร์ทนั้นสามารถเรียกใช้งานการร้องขอ http ได้ แต่ใน service ให้ตั้งค่า pipe พร้อมกับ tap เพื่อตั้งค่าค่าตอบกลับไปยัง BehaviorSubject จากนั้นในคอมโพเนนต์ของคุณที่ต้องการข้อมูลให้ใช้ async pipe เพื่อจัดการการสมัครสมาชิกข้อมูล

นี่คือตัวอย่างโค้ดของบริการ:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject, Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';

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

  private _data: BehaviorSubject<any> = new BehaviorSubject({ properties: [], geometry: [] });
  public data$: Observable<any> = this._data.asObservable();

  constructor(private http: HttpClient){}

  set data(data) {
    this._data.next(data);
  }

  get data() {
    return { ...this._data.value };
  }

  public getEarthquakeData(url): Observable<any[]> {
    return this.http.get<any[]>(url)
      .pipe(
        tap(
          (data: any) => this.data = data
        )
      )
  }
}