问题
I have a service "provided in root" that:
- gets data once from an API
- should handle a mapping on that data
- should provide that data to other components if needed
This data doesn't need to be reloaded throughout the lifecycle of the app. It's only reloaded when the user refreshes the browser. All of the data is going to be used at some point - so it makes no sense to make http requests on each getOneById()
. A filter is faster in this case.
The mockup of the service looks something like this:
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;
}
}
Now I'm lost with these questions:
- Should the service itself subscribe to
items$
?
Or should all member functions, likegetOneById()
subscribe?
(Which could mean, that I can removeitems
. - Should I call
getData()
in the constructor, as I definitely need the values during the run of the app?
Or should it be called the first time the values are actually needed? - How can I tell a component, that it's safe to use
getOneById()
?
回答1:
You shouldn't have items without Observable at all. Something like this should work so you don't make http request when you dont need it
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));
}
来源:https://stackoverflow.com/questions/56818773/how-to-build-a-service-that-gets-values-async-but-also-perfoms-tasks-on-that-dat