Within the service class constructor, I make an http call to the server to fetch product category data and store it in the productCategories array. However, when I try to retrieve the productCategories array in the ngInit() function of my component, I encounter an error stating that the array is undefined.
It seems that the service constructor is making the call to the server and returning before the product category data is actually fetched. So, when the component requests the data using the getCategory(x, y) method of the service, the server call initiated in the constructor is still in progress, resulting in the productCategories array being declared as undefined. Eventually, the server call completes and the productCategories array is logged to the console.
How can I solve this issue?
@Injectable()
export class ProductCategoryService {
private productCategories: ProductCategory[];
private categoriesUrl = "/api/product/categories";
constructor(private http: Http) {
console.log('ProductCategory.constructor() called');
this.getProductCategoriesDb();
}
private getProductCategoriesDb() {
console.log('ProductCategory.getCategories() called');
this.http.get(this.categoriesUrl)
.toPromise()
.then((response: Response) => {
this.productCategories = response.json();
console.log('this.productCategories = ' +
JSON.stringify(this.productCategories));
})
.catch(this.handleError);
}
public getProductCategory(name, type) {
return this.productCategories
.filter(category => (category.name == name && category.type == type))[0];
}
}
Component:
export class ProductCategoryComponent implements OnInit {
category: string;
type: string;
productCategory: ProductCategory = new ProductCategory();
constructor(private route: ActivatedRoute, private productCategoryService:
ProductCategoryService) { }
ngOnInit() {
this.route.params.subscribe(params => {
this.category = params["category"];
this.type = params["type"];
console.log("category = " + this.category)
console.log("type = " + this.type)
this.productCategory =
this.productCategoryService.getProductCategory(this.category, this.type);
console.log("productCategory = " + this.productCategory);
})
}
}
Sequence of logged statements:
ProductCategory.constructor() called ---- product-category.service.ts:27
ProductCategory.getCategories() called ---- product-category.component.ts:23
Error: productCategories array undefined:
ProductCategoryComponent_Host.html:1 ERROR TypeError: Cannot read property 'filter' of undefined at ProductCategoryService.webpackJsonp.../../../../../src/app/product-category/product-category.service.ts.ProductCategoryService.getProductCategory (product-category.service.ts:39) at SafeSubscriber._next (product-category.component.ts:27) at SafeSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.SafeSubscriber.__tryOrSetError (
Finally, the productCategories array is printed --- product-category.service.ts:33
this.productCategories = [{"_id":"599c5d93f36d286317108ffd","name":"Furniture","type":"Living Room","image":[{"label":"Living Room","name":"LivingRoom1.jpg"},{"label":"Sofas","name":"LivingRoom2.jpg"},{"label":"Sleeper","name":"LivingRoom3.jpg"},{"label":"Loveseats","name":"LivingRoom4.jpg"},{"label":"Chairs","name":"LivingRoom5.jpg"},{"label":"Ottomans","name":"LivingRoom6.jpg"},{"label":"Chaisers","name":"LivingRoom7.jpg"},{"label":"Recliners","name":"LivingRoom8.jpg"},{"label":"Sectionals","name":"LivingRoom9.jpg"},{"label":"Occasional Tables","name":"LivingRoom10.jpg"}],"items":["Sofas","Sleepers","Loveseats","Chairs","Ottomans","Chaises","Recliners","Sectionals","Occasional Tables"]}]