2016-03-31 9 views
1

以下のコードはタグ(文字列)のリストを循環し、情報を取得してからサービスからイメージを取得します。次に、新たに作成され、組み立てられたProductItemオブジェクトを、現在イメージが格納されている製品の配列にプッシュします。変数のインスタンスがネストされた約束/オブザーバによって参照されています

var toReturn = []; 
for (var i in tags){ 
    var productItem: ProductItem= new ProductItem(); 

     self.productService.getInfo(tags[i]) 
       .subscribe(function(info){ 
         productItem.info = info; 

         self.productService.getImages(tags[i]) 
          .subscribe(function(imageUrls){ 
            productItem.images = imageUrls; 
            toReturn.push(productItem); 
         }); 
       }); 


} 

ただし、ここに問題があります。

問題は、toReturnアレイで完成します。これらはすべて、tagsアレイ内の最後のタグに対応しています。

これはProductItemの有効範囲と関連している必要があります。私は、タグの最後の要素が最後のproductItemを作成して以来、未完成の約束/監視のすべてがこの最終的なproductItemで成し遂げられていると私は彼らが保持すると期待していたproductItemではないと思います。

誰もこの問題を回避する方法に関するアイデアはありますか?

+0

http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-実用例 – zakki

答えて

-1

ここで問題となるのは、同期ループ(forループ)と非同期処理を混在させることです。すべてのリクエストが終了する前に、処理を終了します。

問題を解決するには、次の要素に反復する前に、要素の処理が完了するまで待つ必要があります。

更新

あなたのコードは次のようにリファクタリングされます。この方法:

var toReturn = []; 
Observable.from(tags).flatMap((tag) => { 
    // STEP1 - load the info for a tag and instantiate 
    // a new product item 

    var productItem: ProductItem = new ProductItem(); 

    // I use forkJoin since we need 'tag', productItem and the 
    // return of getInfo in the next flatMap 
    return Observable.forkJoin([ 
    Observable.of(tag), 
    Observable.of(productItem), 
    self.productService.getInfo(tag) 
    ]); 
}).flatMap((result) => { 
    // STEP2 - load the images for a tag and set 
    // info on the product item 

    var tag = result[0]; 
    var productItem = result[1]; 
    var info = result[2]; 

    productItem.info = info; 

    // I use forkJoin since we need productItem and the 
    // return of getImages in the next map 
    Observable.forkJoin([ 
    Observable.of(productItem), 
    this.productService.getImages(tag) 
    ]); 
}).map((result) => { 
    // STEP3 - set the images on the product item 

    var productItem = result[0]; 
    var images = result[1]; 

    productItem.images = imageUrls; 
    return productItem; 
}).do((productItem) => { 
    // STEP4 - add the product item in the array 

    toReturn.push(productItem); 
}).subscribe(
() => { }, 
() => { }, 
() => { 
    console.log(`completion. The toReturn variable is 
     completely filled.` 
    } 
); 
+0

Thamks! Promiseを作成するために何かをインポートする必要がありますか? – CodyBugstein

+0

あなたは大歓迎です!約束はES6の一部です。だからそれはブラウザの一部であるか、対応するシム(es6-promise)を含める必要があります。 –

+0

私は、TypescriptでAngular 2で作業しています。私はそれを試してみるよありがとう! – CodyBugstein

関連する問題