我正在使用 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;
}
}
Run Code Online (Sandbox Code Playgroud)
这可以通过 RxJs 的shareReplay()来完成。根据变更日志,
shareReplay 返回一个可观察量,它是通过 ReplaySubject 多播的源。该重放主题会在源发生错误时回收,但不会在源完成时回收。这使得 shareReplay 非常适合处理缓存 AJAX 结果之类的事情,因为它是可重试的。然而,它的重复行为与共享不同,因为它不会重复源可观察值,而是重复源可观察值的值。
这使得 user 非常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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以在需要它的组件上返回可观察量,并且如果您查看 Inspect Element 工具上的网络请求选项卡,则不会触发其他 HTTP 请求,因为每次调用时都会返回带有缓存值的可观察量getPlans()。
您可以使用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
}
}
Run Code Online (Sandbox Code Playgroud)
您可以像这样在组件中获取数据:
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
}
Run Code Online (Sandbox Code Playgroud)
如果你想刷新数据,你可以调用该方法
this.sharedService.getPlans();
Run Code Online (Sandbox Code Playgroud)
对于BehaviorSubject来说,这是完全相同的事情,这里会发生什么变化
plans$: Observable<Plan[]> = this.plansSubject.asObservable();
private plansSubject = new BehaviorSubject<Plan[]>;
Run Code Online (Sandbox Code Playgroud)
您可以在组件内部订阅以获取数据,也可以使用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)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5500 次 |
| 最近记录: |