如何只发送一次查询并使结果可用于所有组件? (应该很简单)

How can I send query only once and make result available to all components? (should be quite simple)

我正在为我的个人项目使用 angular 2。所以这是带有一些 sudo 代码的简化场景。

app
 |- main.ts            /* bootstrap the app */
 |- app.component.ts   /* basically with a template: `<nav></nav>
 |                                                    <router-outlet></router-outlet>`.
 |                        And also have providers: [CatService] */
 |- nav.component.ts   /* a navigation bar where each cat's name is an option. 
 |                        ngOnInit(){ this._catService.getCats().then(assignCats) } */
 |
 |- cat.components.ts  /* show the cat's detail selected from the nav component 
                          ngOnInit(){ this._catService.getCat().then(assignCat); } */
 |
 |- cat.service.ts     /* getCats() method to send query to a database for all the cats */

好的。我希望这看起来不会太复杂。

唯一的问题是,我正在调用 this._catService.getCats(),它将查询发送到 nav.componentcat.component 中的数据库。但实际上没有必要发送两次查询,因为我已经知道数据不会经常更改。我现在只能想到两种处理方式:

  1. this._catService.getCats() 中缓存数据库调用的结果,以便在第二次调用时,它可以 return 缓存的值而不是发送第二个查询。

  2. app.component 处进行查询,然后将结果作为 @input 传递给 navcat。但这意味着以后如果我有一个新组件,我也必须将结果传递给它吗?然后最终 app.component 的模板可能会变成这样的:<nav [cats]="queriedCats"></nav><cat [cats]="queriedCats"></cat><somecomponent [cats]="queriedCats"></somecomponent>...这对我来说真的很糟糕。

你怎么看?首选哪种方式?

Which way is the prefered way to do it?

第一种方式更适合并且更好地利用了 Angular 的依赖注入机制。

I am calling the this._catService.getCats() which sends query to the database in both nav.component and cat.component. But there actually has no point sending the query twice as I already know the data is not going to change often.

查询结果变化不大,其实是你自己的实现细节_catService:没必要让其他组件知道,把那个细节封装在里面。

而且,你自己也说过,查询结果几乎是不变的,但仍然在变化(或者可能开始更频繁地变化)。让服务来处理这个问题,让系统的其余部分从负担中解脱出来。

Should I still return a promise from getCats()?

是的,你可以 return Promises。一个很好的例子可以在 angular 文档的 demo plunker (check the app/hero.service.ts file, method getHeroes()) of the Services tutorial page 中找到。

您也可以 return Observable:这在 Angular2 中更常见,而 Observable 实际上是 return由 Htto#get() 编辑。 Angular 文档在这里也解释得很好:RxJS Observable of HTTP Responses.
他们也有一个 demo plunker(再次检查 app/hero.service.ts 文件,方法 getHeroes())展示如何 return Observables。打开两个demo对比一下,我觉得对你很有用。

我将为此利用 Observables 的 do 运算符。这是一个示例:

export class CatsService {
  getCats() {
    if (this.cachedCats) {
      return Observable.of(this.cachedCats);
    } else {
      return this.http.get(...)
         .map(res => res.json())
         .do(data => {
           this.cachedCats = data;
         })
    }
}