我有一个产生json产品列表的端点。我在我的产品代码中定义了一个自定义类类型。我试图从端点获取数据,并将json数组产品转换为Product类的数组。
示例API json(从我的实际数据中简化):
{
"products": [{
"id": 1,
"name": "Product 1",
"materials": [{
"id": 100,
"desc": "wood"
}, {
"id": 101,
"desc": "metal"
}]
}, {
"id": 2,
"name": "Product 2",
"materials": [{
"id": 100,
"desc": "wood"
}, {
"id": 102,
"desc": "brick"
}]
}]
}
我的代码:
loadProducts(){
this.fetchProducts().subscribe(data => {
console.log("the data:", data);
})
}
fetchProducts(): Observable<Product[]> {
return this.http.get("http://example.com/mydata.json")
.map((response) => {
const products = (response.json()).products;
console.log("Converting to json" + products.length);
return products;
})
.map( data => {
console.log("Working on data: ", data);
return new Product(data.id, data.name, data.materials);
});
我希望在我的控制台中看到的是......
"Converting to json 2"
"Working on data: " [object]
"Working on data: " [object]
"the data:" [object,object]
..但我所看到的是......
"Converting to json 2"
"Working on data: " [object,object]
"the data:" [object,object]
我认为.map函数会针对发送给它的每个项目运行。我可以看到,当我第一次调用.map时,它在一个项目(响应)上运行一次 - 我知道有两个产品被返回。我希望第二个map函数可以运行两次 - 每个产品项一次。相反,似乎它被称为一次被传递到产品阵列中。
为了使事情变得更复杂,我还希望将材料列表转换为我创建的Material类类型。我知道我可以用forEach循环来做所有,但我想这样做&#34; React&#34;方式。
答案 0 :(得分:14)
我终于找到了Observable操作的正确组合,以产生我想要的东西。
fetchProducts(): Observable<Product[]> {
return this.http.get("http://examples.com/myData")
.map((response) => {
return response.json().products;
})
.switchMap( productArray => {
return Observable.from(productArray);
})
.map( (productData: any) => {
return new Product(
productData.id,
productData.name,
productData.materials
);
})
.toArray();
}
我误解了Observable.map的工作方式 - 认为当它实际运行在每个数据上时,它会在我的数据中的每个项目上运行..而且我有一个数据来到它 - 一个数组。感谢@jonrsharpe在那里帮助我。
通过使用switchMap从我的数组中返回一个新的Observable,我能够分别发出我的数组中的每一段数据。感谢@ giora-guttsait的帮助。
最后,我需要将流的所有新部分组合回一个数组。 Observable.toArray()为我做了这个。
答案 1 :(得分:1)
在你的情况下,你得到的是这样的东西:
this.http.get(...)
.map(res => res.json().products) // turns this into Observable<Products[]>
.map(products => ... ) // here, products is already an array.
如果你想像在React中那样处理这个数组,意味着为每个产品做一些事情,你可以做类似的事情:
this.http.get(...)
.map(res => res.json().products)
.switchMap(products => Observable.from(products))
此处,Observable.from(products)
返回Observable<Product>
,而switchMap
会使您之前获得的链返回Observable<Product>
。
this.http.get(...)
.map(res => res.json().products)
.switchMap(products => Observable.from(products))
.subscribe(product => console.log(product))
将打印所有这些产品。
免责声明:我没有通过运行来检查此代码,您可能需要一个不同的运算符switchMap
,但这是我记得的有用