製品のjsonリストを生成するエンドポイントがあります。 Productsのコードでカスタムクラスタイプを定義しています。エンドポイントからデータを取得し、製品の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を呼び出したときに、1つのアイテム(応答)に対して1回実行されていることがわかります。また、2つのアイテムが返されていることがわかります。次に、2番目のマップ関数が2回実行されることを期待します-各製品アイテムに対して1回。代わりに、製品の配列で渡されると呼び出されるようです。
さらに複雑なことに、マテリアルのリストを、作成したマテリアルクラスタイプに変換したいと思います。 forEachループでallを実行できることはわかっていますが、これを「React」の方法で実行したいと考えています。
最終的に、私が探していたものを生み出すために、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。
最後に、これらの新しいストリームのピースをすべて1つの配列に結合する必要がありました。 Observable.toArray()がこれを行いました。
あなたの場合、あなたはこのようなものを得ています:
_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))
_
それらの製品をすべて印刷します。
Disclamer:このコードを実行してチェックしていません。switchMap
とは異なる演算子が必要な場合がありますが、これは機能することを覚えています