我正在制作角度應用程式,并且我有一個像這樣的空陣列:
orders: Order[];
order_details: Product[];
然后我在 ngOnInit 中進行服務呼叫以將資料存盤到訂單陣列和 order_details 陣列中,
ngOnInit(): void {
this.getOrders();
}
這是 getOrders() 函式,它應該獲取每個訂單。訂單物件有一個 order_id、product_id 串列,其中包含正在訂購的產品的所有產品 ID 和 order_time
getOrders() {
this.order_service.getOrderList().subscribe({
next: (data) => {
this.orders = data;
for (let order of this.orders) {
for (let val of order.product_ids) {
this.product_service.getProductById(val).subscribe({
next: (data) => {this.order_details.push(data);}
});
}
}
},
});
console.log(this.order_details);
}
getOrderList() 使用api回傳所有訂單
getOrderList(): Observable<Order[]> {
return this.http_client.get<Order[]>(`${this.baseURL}`);
}
getProductById() 使用 api 通過 id 回傳產品
getProductById(id: number): Observable<Product> {
return this.http_client.get<Product>(`${this.baseURL}/${id}`);
}
Order 物件和 Product 物件具有如下欄位
export class Order{
order_id: number;
product_ids: number[];
order_time: String;
}
export class Product{
product_id: number;
product_name: String;
product_image: String;
product_description: String;
product_price: String;
}
我正在嘗試使用 getOrders() 函式來獲取每個訂單,并從每個訂單中訪問產品 id 陣列并按 id 查找每個產品,然后使用 push() 用這些產品填充 order_details 陣列
所以我期待一個 order_details 陣列,其中的產品對應于 orders 陣列中每個訂單提到的 product_ids
但是,這樣做會引發錯誤,并且 order_details 陣列未定義
錯誤型別錯誤:無法讀取未定義的屬性(讀取“推送”)
uj5u.com熱心網友回復:
您尚未初始化空陣列。
order_details: Product[] = [];
您應該在 tsconfig.json 中啟用嚴格模式。嚴格模式可防止在編譯階段出現此類錯誤。
uj5u.com熱心網友回復:
- 你可以編輯
this.product_service.getProductById(val).subscribe({
next: (data) => {this.order_details.push(data);}
});
至:
this.product_service.getProductById(val).subscribe({
next: (dataId) => {this.order_details.push(dataId);}
});
注意:資料 --> 資料ID
- 你應該在你的組件 order_details 中初始化: Product[] = [];
- 您必須檢查 if(data) 然后推送
uj5u.com熱心網友回復:
實際上,我認為您在這里還有另一個問題,因為我假設您希望您的order_details陣列與陣列的順序相同orders。您的實施方式無法保證。
我的建議是執行以下操作:
- 擺脫
order_details變數并按Product以下方式調整您的課程:
export class Order{
order_id: number;
product_ids: number[];
order_time: String;
details?: Product[];
}
- 將訂單定義為 Observable:
orders$: Observable<Order[]>;
- 使用
rxjs運算子在并行 HTTP 請求中“豐富”您的資料(使用forkJoin):
this.orders$ = this.order_service
.getOrderList()
.pipe(
switchMap((orders) =>
forkJoin(
orders.map((order) =>
forkJoin(
order.product_ids.map((product_id) =>
this.product_service.getProductById(product_id)
)
).pipe(map((products) => ({ ...order, details: products })))
)
)
)
);
這將導致orderobjectsdetails屬性被來自的資料“豐富” this.product_service.getProductById(product_id)。
- 使用
async管道監聽orders$observable 的輸出。
uj5u.com熱心網友回復:
你的錯誤只是因為沒有初始化你的陣列:
orders: Order[] = [];
order_details: Product[] = [];
請注意,您當前的設定不會保持請求產品詳細資訊的順序,一旦請求完成,它們將隨機推送到陣列。
建議如下。
簡單示例:https ://stackblitz.com/edit/angular-ivy-2kfwbz?file=src/app/app.component.ts
優化示例:https ://stackblitz.com/edit/angular-ivy-2whd3b?file=src/app/app.component.html
在訂閱 observables 之前,您應該創建一個根據需要轉換資料的管道。
orders只是結果,this.order_service.getOrderList()所以我們可以這樣初始化它。有些人傾向于用$.
export class MyComponent {
orders$: Observable<Order[]> = this.order_service.getOrderList();
constructor(
private order_service: OrderService,
private product_service: ProductService
) {}
}
order_details取決于結果,orders$因此您可以以此為起點創建管道。
order_details$: Observable<Product[]> = this.orders$.pipe(
switchMap((orders) => {
const res: Observable<Product>[] = [];
for (let o of orders) {
for (let id of o.product_ids) {
res.push(this.product_service.getProductById(id));
}
}
return forkJoin(res);
})
);
注意 和 的switchMap使用forkJoin。
forkJoin接受一個 observable 陣列,等待它們全部完成,然后發出一個包含完成值的陣列。請注意,它們確實需要完成,如果您使用的是長期存在的可觀察物件,則可以combineLatest改用。
switchMap是必要的,因為forkJoin回傳一個 observable,并且pipe還回傳一個 observable。如果我們只是使用map. switchMap決議內部可觀察物件。
要在 html 中顯示值,您可以使用異步管道,它會自動訂閱/取消訂閱。這通常是最佳實踐,但并不總是現實的。
<h1>Orders</h1>
<pre>{{ orders$ | async | json }}</pre>
<h1>Order Details</h1>
<pre>{{ order_details$ | async | json }}</pre>
請注意,這沒有優化,因為兩個可觀察物件都在重復請求orders$. 但它既好又簡單。
為了消除重復,您可以保存訂單的結果,然后在填充后,為order_details
orders: Order[] = [];
order_details$: Observable<Product[]> = new Observable();
ngOnInit() {
this.order_service.getOrderList().subscribe((res) => {
this.orders = res;
this.getOrderDetails();
});
}
getOrderDetails() {
const res: Observable<Product>[] = [];
for (let o of this.orders) {
for (let id of o.product_ids) {
res.push(this.product_service.getProductById(id));
}
}
this.order_details$ = forkJoin(res);
}
<h1>Orders</h1>
<pre>{{ orders | json }}</pre>
<h1>Order Details</h1>
<pre>{{ order_details$ | async | json }}</pre>
當然,如果需要,您可以訂閱并將結果保存到區域變數。
order_details: Product[] = [];
getOrderDetails() {
const res: Observable<Product>[] = [];
for (let o of this.orders) {
for (let id of o.product_ids) {
res.push(this.product_service.getProductById(id));
}
}
forkJoin(res).subscribe((res) => this.order_details = res)
}
注意:我假設這些 observables 是簡單的 http 請求的結果,所以取消訂閱是不必要的
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/530282.html
