2017-02-22 8 views
1

私は解決策を見つけようと多くの努力をしており、最終的に私のデータが返されたときに約束を破ると信じています。繰り返し。AngularJS各ループのシーケンシャルチェーン約束

私は、各行をループし、 'menuType'と 'trackMenuIds'という配列を追加して、それをMongoDB呼び出しで検索条件に使用するvm.planWeek.dinnerを持っています。これはうまくいきますが、キー要素は、各ファクトリコールが返されたときです。返されたアイテムのIDを 'trackMenuIds'配列に追加します。これは、すでに返されている項目の配列を作成するため、次の呼び出しで無視することができます。つまり、$ ninを使用します。

vm.reviewWeek = function() { 

    //Array to be updated over each iteration and used in factory call 
    var trackMenuIds = []; 

    angular.forEach(vm.planWeek.dinner, function (day) { 

     //Adds two more items to day(current row) to pass to factory 
     day.menuType = 'dinner'; 
     day.weekIds = trackMenuIds; 

     //Factory call - each time this runs, the 'trackMenuIds' array should have 
     //one more item added from the previous run 
     menuFactory.matchMenuCriteria(day) 
      .then(function (response) { 
      var randomItem = response.data[0]; 
      day.menuItem = {'_id': randomItem._id, 'name': randomItem.name}; 

      //adds the current id to the array to be used for the next run 
      trackMenuIds.push(randomItem._id); 
      }); 
    }); 
}; 

'trackMenuIds'配列を現在の行に追加すると、どのIDでも更新されていません。私はそれをコンソール化すると、実際にはそれらを追加することができますが、約束の一部として信じています。更新された配列を各繰り返しでファクトリコールに渡すほど早く実行していません。

私はチェーンの約束などの手段を試しましたが、うまく動作しないようです。おそらくそれは私の未来の約束になるので、どんな助けでも大いに感謝されるでしょう。

+0

[ループ内のJavaScriptクロージャー - 簡単な実用的な例]の複製が可能です(http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Phil

答えて

1

工場非同期APIへの呼び出しが並行して行われているにデータをプッシュし、その後生のHTTP約束を通じて、ループを実行して完了です。順番に連鎖する必要があります。

vm.reviewWeek = function() { 

    //Array to be updated over each iteration and used in factory call 
    var trackMenuIds = []; 

    //INITIAL empty promise 
    var promise = $q.when(); 

    angular.forEach(vm.planWeek.dinner, function (day) { 

     //Adds two more items to day(current row) to pass to factory 
     day.menuType = 'dinner'; 
     day.weekIds = trackMenuIds; 

     //Factory call - each time this runs, the 'trackMenuIds' array should have 
     //one more item added from the previous run 

     //CHAIN sequentially 
     promise = promise.then(function() { 
      //RETURN API promise to chain 
      return menuFactory.matchMenuCriteria(day); 
     }).then(function (response) { 
      var randomItem = response.data[0]; 
      day.menuItem = {'_id': randomItem._id, 'name': randomItem.name}; 

      //adds the current id to the array to be used for the next run 
      trackMenuIds.push(randomItem._id); 
     }); 
    }); 

    return promise; 
}; 

上記の例では、初期の空の約束を作成しています。 foreachループは、各反復で非同期APIへの呼び出しをチェーンします。

+0

これは完璧に機能しました。 – Andrew

1

$ q.allを使用すると、複数の非同期呼び出しを処理できます。一旦全ての約束は、新しい配列

vm.reviewWeek = function() { 

    //Array to be updated over each iteration and used in factory call 
    var trackMenuIds = []; 

    var dinnersPromise = []; 

    vm.planWeek.dinner.forEach(function (day, ind) { 
     //Adds two more items to day(current row) to pass to factory 
     day.menuType = 'dinner'; 
     day.weekIds = trackMenuIds; 
     dinnersPromise.push(menuFactory.matchMenuCriteria(day)); 
    }); 

    $q.all(dinnersPromise).then(function (arr) { 
     angular.forEach(arr, function (response) { 
      var randomItem = response.data[0]; 
      day.menuItem = {'_id': randomItem._id, 'name': randomItem.name}; 

      //adds the current id to the array to be used for the next run 
      trackMenuIds.push(randomItem._id); 
     }); 
    }); 
} 
+0

これは私にはありません同じ結果、私は次の呼び出しにそれを注入するために、次の呼び出しは、各約束の寝床の結果を取得する必要がありますか? – Andrew

+0

@Andrewの結果は同じかもしれませんが、使用方法は異なります。手動ループでは、約束がいつ実行されるのかわからず、ループがすでに次の反復に入っているとしましょう。現在の約束の値を逃してしまいます。 – digit