在我的angular 6应用程序中,我有一个product_id
,它是一个数组,
product_id: any = ["123", "456"];
ngOnInit:
ngOnInit() {
this.product_id.forEach(element => {
this.httpClient.get('https://api.myjson.com/bins/hiolc').subscribe(res => {
this.productList = [];
res.products.forEach( item => {
this.productList.push(item);
});
})
})
console.log(this.productList);
}
在console.log(this.productList);
中,我需要将预期结果设置为
[{
"product_name": "Product One",
"product_information": {
"template_details": [
{
"template_name": "RACE Template",
"productProperties": [
{
"property_id": 2518427931,
"property_name": "Length",
"property_value": "12 cm"
},
{
"property_id": 2621195440,
"property_name": "Width",
"property_value": "10 cm"
},
{
"property_id": 2621195441,
"property_name": "Height",
"property_value": "20 cm"
}
]
}
]
}
},
{
"product_name": "Product Two",
"product_information": {
"template_details": [
{
"template_name": "RACE Template",
"productProperties": [
{
"property_id": 2518427931,
"property_name": "Length",
"property_value": "15 cm"
},
{
"property_id": 2621195440,
"property_name": "Width",
"property_value": "12 cm"
},
{
"property_id": 2621195441,
"property_name": "Size",
"property_value": "Medium"
}
]
}
]
}
}]
但是会给出空数组[] ..
如何等待服务完成,然后将数据存储到productList
。
我需要forEach this.product_id.forEach(element
,因为在基于foreach的真实应用程序中,我将获得通过url发送的每个产品ID的产品列表。
在发送完所有产品ID之后,请根据forEach
完成整个服务后帮我存储数据,然后获取最终产品列表。
有效的堆叠闪电战: https://stackblitz.com/edit/flatternstructure-dvzpjv
我再次明确,在我的真实应用程序中,我需要传递ID才能像product value
一样获得https://api.myjson.com/bins/hiolc + element
。.
如果我得到最终的productList
,那么我需要对最终的productList
做另一项功能,所以只有我期望最后在productList
中完成的数据,而不是{{1 }} ..
答案 0 :(得分:1)
使用rxjs.concat:
[编辑]
在stackblitz上可用
...
import { concat } from 'rxjs';
import { map } from 'rxjs/operators';
...
ngOnInit() {
this.productList = [];
concat(
this.product_id.map(
element => this.httpClient.get('https://api.myjson.com/bins/hiolc')
)
).pipe(
map((res: any) => this.productList = this.productList.concat(res.products))
).subscribe(res => {
console.log(res);
console.log(this.productList);
});
}
希望有帮助。
答案 1 :(得分:0)
更新:
这将起作用:
import { zip } from 'rxjs'
....
ngOnInit() {
const obs = []
this.product_id.forEach(element => {
obs.push(this.httpClient.get('https://api.myjson.com/bins/hiolc'))
})
zip(...obs).subscribe(res => {
res.forEach(r => this.productList.push(...r.products))
console.log(this.productList)
})
}
stackblitz: https://stackblitz.com/edit/flatternstructure-nk9yha
答案 2 :(得分:0)
您有两个问题:您记录得太早了,并且覆盖了阵列。
首先,登录很快。您触发请求(ids.forEach(id => this.http....)
)。然后在那之后,您执行console.log
-但结果尚未返回。甚至还没有触发请求。这就是为什么您看到空数组的原因。将console.log语句移到this.productList.push(...)
语句下,您会看到它。
第二个问题是,您触发并行请求,并且它们都使用以下行重置产品列表:this.productList = []
;。
您只想这样做一次。
所有这些的更好的版本是:
ngOnInit() {
forkJoin(product_ids) // fire them in parallel.
.pipe(
map(id => this.http.get('https://api.myjson.com/bins/hiolc' + id)), // fetch the things
map(items=> this.productList = this.productList.concat(items)),
)
.subscribe(() => console.log('Done, items:', this.productList));
更好的版本是:
ngOnInit() {
this.someService.getProductItems(productIds)
.subscribe(productList => this.productList = productList);
}
意思是,将Http调用移到服务中,在其中执行所有这些操作,并使组件更清洁,更简单。
答案 3 :(得分:0)
为什么不按角度文档中的描述创建真实的服务?
在这里您要在组件内实现httpClient透明性 https://angular.io/tutorial/toh-pt4#subscribe-in-heroescomponent
我建议您首先创建一个可注入服务,该服务将在像HTTPClient这样的组件构造函数中使用
然后,我将在服务中获取数据并订阅它。
答案 4 :(得分:0)
您能尝试一下吗?
ngOnInit() {
let counter = 0;
this.productList = [];
this.product_id.forEach(element => {
this.httpClient.get('https://api.myjson.com/bins/hiolc').subscribe(res => {
res.products.forEach( item => {
this.productList.push(item);
});
counter = counter + 1;
if(counter === this.product_id.length){
console.log(this.productList);
// call your next operation here
}
})
})
}
答案 5 :(得分:0)
这个怎么样? StackBlitz
import { forkJoin } from 'rxjs';
....
ngOnInit() {
forkJoin(
this.product_id.map(element => this.httpClient.get('https://api.myjson.com/bins/hiolc'))
)
.subscribe((res) => {
this.productList = this.productList.concat(res);
console.log(this.productList);
});
}
答案 6 :(得分:0)
这也可以:
this.productList$ = from(this.product_id).pipe(
mergeMap(() => this.httpClient.get('https://api.myjson.com/bins/hiolc')),
scan((productList, item) => [...productList, item], [])
tap((productList) => console.log(productList))
).subscribe(() => {}) // or async pipe in a template