Ну, как говорит Angular doc, лучше иметь эту логику в сервисе, взгляните на это:
class Service {
constructor(public http: HttpClient) { }
getRestaurants(): Observable<Restaurant> {
return this.http.get<{ /* Specify HTTP response schema */ }>(url).pipe(
// Transformation to actual Restaurants at one place
map(data => data.map(restaurant => new Restaurant()),
// Handle error
catchError(err => {
logError(err);
throw err;
// Or...
return of([]); // Mock data not to crash app
}),
// If multiple subscription are made to same source, it won't do multiple http calls
shareReply(1),
);
}
}
class Component {
restaurants: Restaurant[] = [];
ngOnInit(): void {
// Prefered way
this.restaurants$ = this.service.getRestaurants().pipe(
// If, you pass error down, you'll be able to hendle it here...
catchError(err => {
return of([]);
}),
);
// Alternative
this.cleanUp = this.service.getRestaurants().subscribe(restaurants => {
this.restaurants = restaurants;
});
}
ngOnDestroy(): void {
this.cleanUp.unsubscribe();
}
}
HTML
<!-- Observable -->
<div *ngFor="let restaurant of restaurants$ | async">
{{restaurant | json}}
</div>
<!-- Non-Observable -->
<div *ngFor="let restaurant of restaurants">
{{restaurant | json}}
</div>
Я переключил ваш код с обещания на наблюдаемые, потому что наблюдаемые являются одним из самых больших преимуществ использования Angular. Наблюдаемые могут быть отменены, хорошо читаются в шаблонах и многих других, которые я могу вспомнить за один день.
Наблюдаемые значения очень сильны, вы можете всегда иметь свежую информацию, основанную на других наблюдаемых. Посмотрите, это может дать вам некоторые идеи ...
interface ApiResponse<type> {
awaitingNewValues: boolean;
error: null | any;
response: type;
}
class Service {
currentRestaurantID = new BehaviourSubject(1);
currentRestaurantInfo: Observable<ApiResponse<Restaurant>>;
constructor(private http: HTTPClient) {
let latestRestaurants: ApiResponse<Restaurant | undefined> = {
awaitingNewValues: true,
error: null,
response: [],
};
currentRestaurantInfo = this.currentRestaurantID.pipe(
switchMap(restaurantID => {
return concat(
// This will notify UI that we are requesting new values
of(Object.assign({}, latestRestaurants, { awaitingNewValues: true })),
// The actual call to API
this.http.get(`${apiUrl}/${restaurantID}`).pipe(
// Wrap response in metadata
map(restaurant => {
return {
awaitingNewValues: false,
error: null,
response: restaurant,
}
}),
// Notify UI of error & pass error
catchError(err => {
return of({
awaitingNewValues: true,
error: err,
response: undefined,
});
}),
),
);
}),
// Save last response to be used in next api call
tap(restaurants => this.latestRestaurants = restaurants),
// Prevent calling API too many times
shareReplay(1),
);
}
}