我在angular 4应用程序中有一个服务,使用以下构造函数:
constructor(private readonly http: Http) {
this.http.get(this.originUrl + 'api/ProductCategories/').subscribe(result => {
this.categories = result.json();
});
}
以及此服务中的一项功能,以获取一个类别ID。
findCategory(fullSlug: string): number {
return this.categories.filter(c=>c.fullSlug == fullSlug)[0].id;
}
我需要在填充类别列表后从组件中调用此函数。应用程序加载一次后,这是正常的,因为服务是从app.module加载的,但是当我重新加载页面时(F5)我在findCategory函数中得到错误“无法读取未定义的属性'过滤器'。
感谢。
答案 0 :(得分:1)
我的this.categories
属性正在填充 async ,因此在您无法从服务内部控制的其他公共方法中使用它时,需要考虑到这一点。< / p>
<强>更新强> 由于在这种情况下证明数据仅从数据源检索一次是重要的,因此我建议从服务中完全可观察到。这意味着服务将始终返回可观察的结果,并始终让消费者处理订阅。
仅加载数据一次的技巧是使用share
运算符。它会使categories$
可观察的热(read more on the topic here)。简而言之 - 它只会转到数据源一次,然后让所有订阅者共享已经检索到的结果(参见下面的更新代码)。
我建议将订阅类别的责任委托给服务的使用者,然后将要进行过滤的数据作为参数添加到filter
函数中。击>
这可以确保您在进行过滤时始终使用加载的数据。
在服务中(暂时为YourService.ts
):
originUrl = "....";
categories$: Observable<YourCategoryType[]>;
constructor(private readonly http: Http) {
this.categories$ = this.http.get(this.originUrl + 'api/ProductCategories/')
.map(res => res.json())
.share(); // <- Makes sure the call is only made ones, then re-uses the result
}
findCategory(fullSlug: string): Observable<number> {
return this.categories$
.map(cats => cats.filter(cat => cat.fullSlug === fullSlug)[0].id);
}
在消费者中,例如组件:
categoryId: number;
constructor(private yourService: YourService) {}
someMethod(fullSlug: string) {
this.yourService
.findCategory(fullSlug)
.subscribe(catId => this.categoryId = catId);
}
答案 1 :(得分:0)
它真的无法预测,当你在服务的构造函数中使用它时,你无法控制http请求。
我建议你有一个&#34;帮助&#34;而不是方法,以便您可以控制流量。在该辅助方法中,我们只需检查value
是否为categories$
。如果是,请进行http呼叫。然后在您的服务中使用该方法并执行您的魔法;)在您的服务中这样的事情:
undefined
然后,如上所述,在您的其他服务方法中,只需调用上述服务方法......例如,当您从组件中调用categories$: Observable<ProductCategory[]>
getCategories() {
if(this.categories$ === undefined) {
this.categories$ = this.http.get(this.originUrl + 'api/ProductCategories/')
.map(res => res.json())
}
return this.categories$
}
时,这将在您的服务中进行:
findCategory
..您可以在组件中订阅哪个结果。