Reputation: 84
I have a service function like the one below.
getByIdWithCategory(id: number): Observable<Product> {
const category = new Category();
category.name = 'sample category';
return this.httpClient.get<Product>(this.baseUrl + `/${id}`)
.pipe(map(product => ({...product, category})));
}
I get the value returned from here with the async pipe in the template file. But I need to get the category from api. I need to subscribe for this. But then I can't unsubscribe. What is the best practice for this?
The function below does exactly what I want. But I couldn't find a way to unsubscribe from the api call I get the category from.
getByIdWithCategory(id: number): Observable<Product> {
return this.httpClient.get<Product>(this.baseUrl + `/${id}`)
.pipe(
tap(product => {
this.categoryService.getById(product.id)
.subscribe(category => {
product.category = category;
});
})
);
}
Here's how in my product class.
export class Product {
id: number;
title: string;
price: number;
description: string;
categoryId: number;
image: string;
category: Category;
}
Upvotes: 1
Views: 857
Reputation: 31125
Try to avoid nested subscriptions. And subscribing inside the tap
operator looks particularly inelegant. Instead you could use switchMap
to map from one observable to another. And pipe map
to the inner observable and return the whole object with the category
property.
Try the following
getByIdWithCategory(id: number): Observable<Product> {
return this.httpClient.get<Product>(this.baseUrl + `/${id}`).pipe(
switchMap((product: Product) => {
this.categoryService.getById(product.id).pipe(
map((category: Category) => ({
...product,
category: category
}))
)
})
);
}
Upvotes: 1