在服务中拥有持久数据的正确方法

时间:2019-02-28 16:52:10

标签: angular rxjs observable

我仅尝试从数据库中获取一次items(我希望它们不会改变)。最初加载 home-page.component.ts 时,HomePageComponent.items的设置正确,但是如果我先从HomePageComponent导航到ProfilePageComponent,然后又回到{{ 1}},因为HomePageComponent已经解决,订阅回调不会重新运行,并且itemsService.items$也不会重新初始化。这是我目前正在使用的解决方法,但是感觉太笨拙,无法正确处理这种情况。

home-page.component.ts

HomePageComponent.items

items.service.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;
    }
}

2 个答案:

答案 0 :(得分:5)

该组件不应该知道任何缓存,您需要对其进行抽象。该服务可以缓存检索到的项目,然后将这些项目返回到使用of包装成可观察对象的任何后续调用。服务本身可以使用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));
  }
}

出于示例的目的,我添加了一个名为IItem的接口,以便可以强烈地键入调用和签名。您可以将其替换为所需的任何接口类型。

答案 1 :(得分:0)

取消订阅者的观察,以销毁主页组件。

itemOb: any;

将此视为全局

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

尝试一下可以解决您的问题