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:
getCus
1) You can simply save downloaded data in your service:
export class CustomersService {
protected _customers: Array;
constructor(public http: Http) {}
public getCustomers(): Observable> {
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))
.subscribe((customers: Array) => {
this._customers = customers;
observer.next(this.customers);
observer.complete();
});
});
}
}
2) Shorter approach taking refresh parameter:
export class CustomersService {
protected _customers: Array;
constructor(public http: Http) {}
public getCustomers(refresh?: boolean): Observable> {
if (!refresh && this._customers) {
return Observable.of(this._customers);
}
return this.http
.get(this.baseURI + this.url)
.map((c: Response) => (c.json() as Array))
.do((customers: Array) => {
this._customers = customers;
});
});
}
}
3) Taking advantage of ReplaySubject:
export class CustomersService {
protected _customers$: ReplaySubject> = new ReplaySubject(1);
protected _customersInitialized: boolean;
constructor(public http: Http) {}
public getCustomers(refresh?: boolean): Observable> {
if (refresh || !this._customersInitialized) {
this._customersInitialized = true;
this.http
.get(this.baseURI + this.url)
.map((c: Response) => (c.json() as Array))
.subscribe((customers: Array) => {
this._customers$.next(customers);
});
}
return this._customers$.asObservable().skip(+refresh).distinctUntilChanged();
}
}
And then:
this.customersService.getCustomers()
.subscribe(customers => this.customers = 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 {
return this._customers;
}