如何构建一个服务,既能获取异步值,又能对数据执行任务,比如过滤?
How to build a service that gets values async but also perfoms tasks on that data, like filtering?
我有一项服务“在 root 中提供”:
- 从 API
中获取一次数据
- 应该处理该数据的映射
- 如果需要,应将该数据提供给其他组件
在应用的整个生命周期中不需要重新加载此数据。它仅在用户刷新浏览器时重新加载。所有的数据都将在某个时候被使用——所以在每个 getOneById()
上发出 http 请求是没有意义的。在这种情况下,过滤器更快。
该服务的模型如下所示:
export class MyTypeService {
items: MyType[] = [];
items$ = new BehaviorSubject<MyType[]>(this.items);
constructor(private http: HttpClient) { }
getData(): Subscription {
return this.http.get<SearchResult>(
'path'
).pipe(
map((response: any) => {
this.items = response;
return this.items;
}),
catchError(error => {
// removed from the question for simplicty
this.handleError(error);
return of([]);
})
).subscribe(result => this.items$.next(result));
}
getOneById(id: string): MyType|null {
for (let item of this.items) {
if (item.id === id) {
return item;
}
}
return null;
}
}
现在我对这些问题感到困惑:
- 服务本身是否应该订阅
items$
?
或者所有成员函数,比如getOneById()
都应该订阅吗?
(这可能意味着我可以删除 items
.
- 我是否应该在构造函数中调用
getData()
,因为我确实需要应用程序 运行 期间的值?
或者是否应该在第一次实际需要值时调用?
- 我如何告诉一个组件,它可以安全使用
getOneById()
?
你根本不应该拥有没有 Observable 的项目。
像这样的东西应该可以工作,这样你就不会在不需要的时候发出 http 请求
itemsSub: BehaviorSubject<any[]> = new BehaviorSubject(null);
getItems(): Observable<any[]> {
return this.itemsSub.pipe(mergeMap(items => {
if (items) {
return of(items); // Return items if you already have them
} else {
// If you don't have them, get them and emit on subject
return this.http.get().pipe(tap((items) => this.itemsSub.next(items)));
}
}))
}
getItemsFiltered() {
return this.getItems().pipe(filter(items => !!items));
}
我有一项服务“在 root 中提供”:
- 从 API 中获取一次数据
- 应该处理该数据的映射
- 如果需要,应将该数据提供给其他组件
在应用的整个生命周期中不需要重新加载此数据。它仅在用户刷新浏览器时重新加载。所有的数据都将在某个时候被使用——所以在每个 getOneById()
上发出 http 请求是没有意义的。在这种情况下,过滤器更快。
该服务的模型如下所示:
export class MyTypeService {
items: MyType[] = [];
items$ = new BehaviorSubject<MyType[]>(this.items);
constructor(private http: HttpClient) { }
getData(): Subscription {
return this.http.get<SearchResult>(
'path'
).pipe(
map((response: any) => {
this.items = response;
return this.items;
}),
catchError(error => {
// removed from the question for simplicty
this.handleError(error);
return of([]);
})
).subscribe(result => this.items$.next(result));
}
getOneById(id: string): MyType|null {
for (let item of this.items) {
if (item.id === id) {
return item;
}
}
return null;
}
}
现在我对这些问题感到困惑:
- 服务本身是否应该订阅
items$
?
或者所有成员函数,比如getOneById()
都应该订阅吗?
(这可能意味着我可以删除items
. - 我是否应该在构造函数中调用
getData()
,因为我确实需要应用程序 运行 期间的值?
或者是否应该在第一次实际需要值时调用? - 我如何告诉一个组件,它可以安全使用
getOneById()
?
你根本不应该拥有没有 Observable 的项目。 像这样的东西应该可以工作,这样你就不会在不需要的时候发出 http 请求
itemsSub: BehaviorSubject<any[]> = new BehaviorSubject(null);
getItems(): Observable<any[]> {
return this.itemsSub.pipe(mergeMap(items => {
if (items) {
return of(items); // Return items if you already have them
} else {
// If you don't have them, get them and emit on subject
return this.http.get().pipe(tap((items) => this.itemsSub.next(items)));
}
}))
}
getItemsFiltered() {
return this.getItems().pipe(filter(items => !!items));
}