2

mongoDBデータベースにクエリを実行し、いくつかの結果をオブジェクトに返す関数をNodeで構築しています。ただし、オブジェクトを正しくセットアップするのに問題があります。これが私のコードです:

MongoDB ルックアップを呼び出す関数

  $scope.listItems = $resource('http://10.1.1.21\\:3000/api/uniques/:query');

  var itemsToList = [
    'designer',
    'store',
    'category'
  ]

  $scope.uniqueLists = {};

  for(var i = 0; i<itemsToList.length; i++){
    $scope.uniqueLists[itemsToList[i]] = [];  
    $scope.listItems.get({query:itemsToList[i]}, function(data){ 
        console.log(itemsToList); // Returns ["designer", "store", "Category"] x3
        console.log(itemsToList[i]); // Returns undefined, undefined, undefined
        console.log('i = ' + i); // Returns 3, 3, 3 (which is really odd, ideas?)

         $scope.uniqueLists[i] = data.query;

    });
  }

このコードの問題は、上記のコメントにあります。奇妙なことに、i == 33 つのループすべてで、 に等しいはずのとき0に、1で終了し2ます。

私の質問は

ここで何が起こっているのかを明らかにできる人はいますか? Node の非同期動作と関係があるのか​​もしれませんが、ここで本当に途方に暮れています。

追加情報

アクセスしている私のExpressJS呼び出しはここにあります。ご覧のとおり、(ponse) を介してデータが利用可能になります。私の知る限り、ここまたはここに渡すことはできません。$scope.listItemsexpressresiitemsToList

exports.uniqueEntries = function(req, res){
    var query = req.params.query;
    console.log(query);
    db.products.distinct(query, function(err, results){
        if (err) {
            console.log("Lookup Error: " + err);
        } else{
            res.json({
                query:results  
            });
        }       
    });
}

おそらく問題は、expressJSルックアップが終了するまでに、3 つのforループが終了し、i == 2. コンソールがそれをログに記録する理由がわかりません。i ==3また、次のループに進む前にルックアップが確実に終了するようにループをブロックする方法もわかりませんfor

4

2 に答える 2

5

$resourceを含むメソッドget()は非同期です。したがって、それらのコールバックは後で呼び出されます。そして、この場合、laterforループが完了するまで実行された後です。

コールバック内のステートメントについては、iはすでに にインクリメントされています。これが、 、、またはforで3はなくなった理由です。012

console.log('i = ' + i);

callback の周りにクロージャーiを作成することで、インクリメントされた の各値を保持できます。function

function createCallback(itemsToList, i) {
  return function (data) {
      console.log(itemsToList); // Returns ["designer", "store", "Category"] x3
      console.log(itemsToList[i]); // Returns undefined, undefined, undefined
      console.log('i = ' + i); // Returns 3, 3, 3 (which is really odd, ideas?)

       $scope.uniqueLists[i] = data.query;
  };
}

for(var i = 0; i<itemsToList.length; i++){
  $scope.uniqueLists[itemsToList[i]] = [];  
  $scope.listItems.get({query:itemsToList[i]}, createCallback(itemsToList, i));
}

itemsToListが であると仮定する別のオプションは、反復子がクロージャーになるため、ループの代わりArrayに使用することができます。.forEach()for

itemsToList.forEach(function (item, i) {
  $scope.uniqueLists[item] = [];
  $scope.listItems.get({query:item}, function(data){ 
    console.log(itemsToList);
    console.log(itemsToList[i]);
    console.log('i = ' + i);

    $scope.uniqueLists[i] = data.query;
  });
});
于 2013-07-14T08:32:04.390 に答える
0

jQuery のドキュメント ( http://api.jquery.com/jQuery.get/ ) を見ると、 $.get が次の略であることがわかります。

$.ajax({
    url: url,
    data: data,
    success: success,
    dataType: dataType
});

ajax 呼び出しの async プロパティは、デフォルトで true に設定されています.. ( http://api.jquery.com/jQuery.ajax/ ) ajax 呼び出しの get リクエストを、async プロパティを false に設定して変更します。それがここでの問題です。

于 2013-07-14T08:38:27.233 に答える