在Angular $ resource函数的回调中,变量突然变为未定义

JVG*_*JVG 2 javascript asynchronous mongodb node.js

我正在Node中构建一个函数来查询我的mongoDB数据库并将一些结果返回到一个对象中.我无法正确设置对象.这是我的代码:

调用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;

    });
  }
Run Code Online (Sandbox Code Playgroud)

此代码的问题在上面的注释中.奇怪的是,i == 3对于所有3个循环,当它应该相等01,然后完成2.

我的问题是

任何人都可以了解这里发生的事情吗?它可能与Node的异步行为有关,但我真的很茫然.

附加信息

我正在访问的ExpressJS电话$scope.listItems是在这里,你可以看到express通过res(ponse)提供数据,据我所知,我无法传入iitemsToList在这里:

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  
            });
        }       
    });
}
Run Code Online (Sandbox Code Playgroud)

也许问题是,在expressJS查找完成时,三个for循环已完成并且i == 2.我不知道为什么控制台会记录它i ==3,我也不知道如何阻止循环以确保在继续下一个for循环之前完成查找.

Jon*_*ski 5

$resource方法,包括get(),是异步的.因此,他们的回调将在稍后调用.并且,在这种情况下,稍后for循环运行完成之后.

对于回调中的任何语句,i将会增加到3,这就是为什么它不再01,或者2为:

console.log('i = ' + i);
Run Code Online (Sandbox Code Playgroud)

你可以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));
}
Run Code Online (Sandbox Code Playgroud)

另一个选项,假设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;
  });
});
Run Code Online (Sandbox Code Playgroud)