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
)
)
}
}
