使用 Angular 2 中的 Observables 获取数据一次 [英] Fetch data once with Observables in Angular 2
问题描述
我有一个服务,它从我的许多 Angular 2 组件中多次使用.它从 Web API 获取客户数据并返回一个 Observable:
I have a service, what is used several times from a lot of my Angular 2 components. It fetches customer data from a Web API and returns an Observable:
getCustomers() {
return this.http
.get(this.baseURI + this.url)
.map((r: Response) => {
let a = r.json() as Customer[];
return a;
});
}
我将此服务注入到我的根组件中,并且在每个想要访问客户的组件中都注入了我订阅的 Observable:
I inject this service in my root component, and in every component that wants to access the customers I just subscribe to that Observable:
this.customerService.getCustomers().subscribe(v => this.items = v);
然而,订阅我的 Observable 的每个组件都会导致 HTTP 请求的另一次执行.但是只获取一次数据就足够了.如果我尝试 share(),它并不能解决我的问题:
However, every component who subscribes to my Observable causes another execution of the HTTP-request. But to fetch the data only once is enough. If I try share(), it does not solve my problem:
getCustomers() {
return this.http
.get(this.baseURI + this.url)
.map((r: Response) => {
let a = r.json() as Customer[];
return a;
}).share();
}
还是一样的问题.我必须使用哪些运算符才能只获取一次数据?
Still the same issue. Any proposals which operators I have to use to only fetch data once?
推荐答案
1) 您可以简单地将下载的数据保存在您的服务中:
1) You can simply save downloaded data in your service:
export class CustomersService {
protected _customers: Array<Customer>;
constructor(public http: Http) {}
public getCustomers(): Observable<Array<Customer>> {
return new Observable(observer => {
if (this._customers) {
observer.next(this._customers);
return observer.complete();
}
this.http
.get(this.baseURI + this.url)
.map((r: Response) => (r.json() as Array<Customer>))
.subscribe((customers: Array<Customer>) => {
this._customers = customers;
observer.next(this.customers);
observer.complete();
});
});
}
}
2) 采用 refresh
参数的更短方法:
2) Shorter approach taking refresh
parameter:
export class CustomersService {
protected _customers: Array<Customer>;
constructor(public http: Http) {}
public getCustomers(refresh?: boolean): Observable<Array<Customer>> {
if (!refresh && this._customers) {
return Observable.of(this._customers);
}
return this.http
.get(this.baseURI + this.url)
.map((c: Response) => (c.json() as Array<Customer>))
.do((customers: Array<Customer>) => {
this._customers = customers;
});
});
}
}
3) 利用ReplaySubject
:
export class CustomersService {
protected _customers$: ReplaySubject<Array<Customer>> = new ReplaySubject(1);
protected _customersInitialized: boolean;
constructor(public http: Http) {}
public getCustomers(refresh?: boolean): Observable<Array<Customer>> {
if (refresh || !this._customersInitialized) {
this._customersInitialized = true;
this.http
.get(this.baseURI + this.url)
.map((c: Response) => (c.json() as Array<Customer>))
.subscribe((customers: Array<Customer>) => {
this._customers$.next(customers);
});
}
return this._customers$.asObservable().skip(+refresh).distinctUntilChanged();
}
}
然后:
this.customersService.getCustomers()
.subscribe(customers => this.customers = customers);
您还可以通过这种方式公开 SomeService
中始终最新的 customers
字段以用于只读目的(例如在模板中显示):
You can also expose the always up-to-date customers
field from SomeService
for read only purposes (like displaying in the templates) this way:
public get customers(): ReadonlyArray<Customer> {
return this._customers;
}
这篇关于使用 Angular 2 中的 Observables 获取数据一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!