Reputation: 854
I'm trying to fetch items
from a database only once (I don't expect them to change). When I initially load home-page.component.ts the HomePageComponent.items
gets correctly set however if I navigation away from HomePageComponent
to ProfilePageComponent
and then back to HomePageComponent
because the itemsService.items$
has already been resolved the subscribe callback isn't rerun and HomePageComponent.items
isn't reinitialized. This is the current workaround I'm using but it feels too clunky to be the correct way of handling this situation.
home-page.component.ts
ngOnInit() {
this.itemsService.items$.subscribe((items:item) => {
// Is only called once after items are initalially fetched over http
this.items = items;
this.itemsService.addItems(items);
});
if(this.itemsService.foundItems){
this.items= this.itemsService.items;
}
}
items.service.ts
export class ItemsService {
private items = new BehaviorSubject(null);
items$ = this.items.asObservable();
foundItems = null;
constructor(private httpClient: HttpClient){
this.items.next(httpClient.post<any>(myUrl,myQuery).subscribe(this.items));
}
addItems(items){
this.foundItems = items;
}
}
Upvotes: 3
Views: 444
Reputation: 62213
The component should not be aware of any caching, you need to abstract that. The service can cache the retrieved items and then return the items to any subsequent calls wrapped in an observable using of
. The service itself can cache the result of the call using tap
.
home-page.component.ts
ngOnInit() {
this.itemsService.getItems().subscribe((items) => {
this.items = items;
});
}
items.service.ts
import { map, tap } from 'rxjs/operators';
import { of } from 'rxjs';
export interface IItem {
}
export class ItemsService {
items: IItem[];
constructor(private httpClient: HttpClient){
}
getItems() : Observable<IItem[]> {
return this.items
? of(this.items)
: this.httpClient.get<IItem[]>(myUrl).pipe(tap((data) => this.items = data));
}
}
For the purposes of the example I added an interface named IItem so I could strongly type the calls and signatures. You can replace that with whatever interface type you needed.
Upvotes: 6
Reputation: 73
unsubscribe your observer on destroy of home-page component.
itemOb: any;
take this as global
ngOnInit() {
this.itemOb = this.itemsService.items$.subscribe((items:item) => {
// Is only called once after items are initalially fetched over http
this.items = items;
this.itemsService.addItems(items);
});
if(this.itemsService.foundItems){
this.items= this.itemsService.items;
}
}
ngOnDestroy() {
if (this.itemOb) {
this.itemOb.unsubscribe(); }
}
Try this your problem can be resolved
Upvotes: 0