即使在订阅方法中进行赋值,数组仍然未定义



在我的angular应用程序中,数组productLocations在订阅中的ngOnInit方法中分配,稍后在方法中使用,但它仍然未定义。从Stackoverflow上的搜索来看,每个人都在说要在订阅中移动分配。它已经在订阅中,但我收到错误。如何正确地按顺序执行?

ERROR TypeError: Cannot read property 'forEach' of undefined
at AddProductComponent.populateProductLocation

组件文件

export class AddProductComponent implements OnInit, OnDestroy {
form: FormGroup;
productManufacturerOptions: ProductManufacturer[] = [];
filteredProductManufacturerOptions: Observable<ProductManufacturer[]>;
productModelOptions: ProductModel[] = [];
filteredProductModelOptions: Observable<ProductModel[]>;
productCategoryOptions: ProductCategory[] = [];
filteredProductCategoryOptions: Observable<ProductCategory[]>;
product: Product = new Product();
branches: Branch[] = [];
productLocations: ProductLocation[];
productPrices: ProductPrice[];
priceLists: PriceList[] = [];
editMode = false;
private _unsubscribeAll: Subject<any>;
fileToUpload: File = null;
constructor(
private http: HttpClient,
private _formBuilder: FormBuilder,
private productManufacturerService: ProductManufacturerService,
private productModelService: ProductModelService,
private productCategoryService: ProductCategoryService,
private productService: ProductService,
private branchService: BranchService,
private router: Router,
private route: ActivatedRoute,
private _fuseProgressBarService: FuseProgressBarService,
private priceListService: PriceListService,
private cd: ChangeDetectorRef
) {
this._unsubscribeAll = new Subject();
this.initForm();
if (this.route.snapshot.url[0].path == 'edit' && localStorage.getItem("editProductId")) {
this.editMode = true;
}
}
ngOnInit(): void {
this._fuseProgressBarService.show();
if (this.editMode) {
this.productService.get(localStorage.getItem("editProductId"))
.subscribe((result: any) => {
this.product = new Product(result);
console.log("Product", this.product);
// this.productLocations = result.locations;
this.productLocations = this.product.locations;
this.productPrices = this.product.prices;
this.populateUpdateData(result);
});
}
forkJoin([this.productManufacturerService.getList(),
this.productModelService.getList(),
this.productCategoryService.getList(),
this.branchService.getList(),
this.priceListService.getList()
])
.subscribe((results: any) => {
this.productManufacturerOptions = results[0];
this.productManufacturerStart();
this.productModelOptions = results[1];
this.productModelStart();
this.productCategoryOptions = results[2];
this.productCategoryStart();
this.branches = results[3];
this.priceLists = results[4];
},
error => { },
() => {
if (this.editMode) {
this.populateProductLocations();
this.populatePriceLists();
}
else {
this.initProductLocations();
this.initPriceLists();
}
this._fuseProgressBarService.hide();
});
}
initForm() {
this.form = this._formBuilder.group({
id: [''],
partNumber: ['', Validators.required],
description: ['', Validators.required],
replaceNumbers: this._formBuilder.array([]),
manufacturer: [null, Validators.required],
model: [null, Validators.required],
category: [null, Validators.required],
cost: ['', Validators.required],
locations: this._formBuilder.array([]),
prices: this._formBuilder.array([]),
featuredImage: [null]
});
}
initProductLocations() {
this.branches.forEach(branch => {
this.initProductLocation(branch)
});
}
initProductLocation(branch) {
const control = <FormArray>this.form.controls['locations'];
var a = this._formBuilder.group({
branch: [branch, Validators.required],
location: [null, Validators.required],
quantity: [null, Validators.required]
});
control.push(a);
}
populateProductLocations() {
this.branches.forEach(branch => {
this.populateProductLocation(branch)
});
}
populateProductLocation(branch) {
const control = <FormArray>this.form.controls['locations'];
var a;
var productLocationBranchIds = [];    
this.productLocations.forEach(productLocation => {
productLocationBranchIds.push(productLocation.branch.id)
});
console.log("ProdIDS", productLocationBranchIds);
if (productLocationBranchIds.includes(branch.id)) {
this.productLocations.forEach(productLocation => {
if (branch.id == productLocation.branch.id) {
a = this._formBuilder.group({
branch: [productLocation.branch, Validators.required],
location: [productLocation.location, Validators.required],
quantity: [productLocation.quantity, Validators.required]
});
}
});
}
else {
console.log("In else");
a = this._formBuilder.group({
branch: [branch, Validators.required],
location: [null, Validators.required],
quantity: [null, Validators.required]
});
}
control.push(a);
}

initPriceLists() {
this.priceLists.forEach(priceList => {
this.initPriceList(priceList)
});
}
initPriceList(priceList) {
const control = <FormArray>this.form.controls['prices'];
var a = this._formBuilder.group({
priceList: [priceList, Validators.required],
price: [null, Validators.required]
});
control.push(a);
}
populatePriceLists() {
this.priceLists.forEach(priceList => {
this.populatePriceList(priceList)
});
}
populatePriceList(priceList) {
const control = <FormArray>this.form.controls['prices'];
var a;
var productPricesPriceListIds = [];
this.productPrices.forEach(productPrice => {
productPricesPriceListIds.push(productPrice.priceList.id)
});
if (productPricesPriceListIds.includes(priceList.id)) {
this.productPrices.forEach(productPrice => {
if (priceList.id == productPrice.priceList.id) {
a = this._formBuilder.group({
priceList: [productPrice.priceList, Validators.required],
price: [productPrice.price, Validators.required]
});
}
});
}
else {
a = this._formBuilder.group({
priceList: [priceList, Validators.required],
price: [null, Validators.required]
});
}
control.push(a);
}
get replaceNumbers(): FormArray {
return this.form.get('replaceNumbers') as FormArray;
}
createReplaceNumber(): FormGroup {
return this._formBuilder.group({
partNumber: ['', Validators.required]
});
}
addExistingReplaceNumber(value): FormGroup {
return this._formBuilder.group({
partNumber: [value, Validators.required]
});
}
addReplaceNumber() {
this.replaceNumbers.push(this.createReplaceNumber());
}
removeReplaceNumber(index: number) {
this.replaceNumbers.removeAt(index);
}
populateUpdateData(product) {
this.form.get('id').setValue(product.id);
this.form.get('partNumber').setValue(product.partNumber);
this.form.get('description').setValue(product.description);
this.form.get('manufacturer').setValue(product.manufacturer);
this.form.get('model').setValue(product.model);
this.form.get('category').setValue(product.category);
this.form.get('cost').setValue(product.cost);
let rs = product.replaceNumbers;
rs.forEach(element => {
this.replaceNumbers.push(this.addExistingReplaceNumber(element.partNumber));
});
}
ngOnDestroy(): void {
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

这可能是因为以下块的执行时间比订阅的执行时间早:

if (this.editMode) {
this.populateProductLocations();
this.populatePriceLists();
}

要验证这一点,您可以在该块中以及在分配值的订阅中执行console.log(或放置断点(。

您应该考虑重构代码,使this.populateProductLocations()位于同一代码块中的this.productLocations = this.product.locations;之后,或者等待this.productService.get(localStorage.getItem("editProductId"))完成(可能是swithcMapcombineLatestwithLatestFrom(。

使用ForkJoin

forkJoin也应该工作,因为它等待所有可观察到的东西完成,而且既然你已经有了它,你可以把你的代码移到forkJoin中,类似这样(我注释掉了现有的代码,以澄清添加了什么(:

forkJoin([
// this.productManufacturerService.getList(),
// this.productModelService.getList(),
// this.productCategoryService.getList(),
// this.branchService.getList(),
// this.priceListService.getList(),
this.productService.get(localStorage.getItem("editProductId"))
])
.subscribe((results: any) => {
// this.productManufacturerOptions = results[0];
// this.productManufacturerStart();
// this.productModelOptions = results[1];
// this.productModelStart();
// this.productCategoryOptions = results[2];
// this.productCategoryStart();
// this.branches = results[3];
// this.priceLists = results[4];
this.product = new Product(result);
this.productLocations = this.product.locations;
this.productPrices = this.product.prices;
this.populateUpdateData(results[5]);
},

最新更新