所以我很沮丧,似乎无法理解发生了什么。我有一个需要命令数组的函数。

var collection = [{ordernumber: 1, href: 'FileDetails.aspx?FileId=1234'},
                  {ordernumber: 2, href: 'FileDetails.aspx?FileId=1478'}];
var OrdersListToImport = [];

function loopOrders(collection, callback) {
  for(var i = 0; i < collection.length; i++) {
    console.log('processing order #: ' + collection[i].ordernumber);
    var answersReturned = 0;
    db.needsImported(collection[i].ordernumber, function(answer) {
      if (answer) {
        OrdersListToImport.push(collection[i]);
        //console.log(collection[i]);
      }
      if (++answersReturned == collection.length) {
        callback();
      }

    });
  }

}


NeedsImported功能如下:

needsImported: function(ordernumber, callback) {
    pool.query('Select controlnumber From orders Where ordernumber = ?', [ordernumber], function(err, result) {
      if (!err) {
        if (result.length == 0) {
          callback(true);
        }
        else {
          callback(false);
        }
      }
    });
  }


在db.needsImported的回调函数中时,collection [i]变为未定义。这让我发疯了,所以我制作了一个小样本文件来查看是否有我无法从回调函数内部访问参数的原因。它按预期工作,只推偶数。这是示例:

var nums = [];
var collection = [1,2,3,4,5,6,7,8,9,10];

displayValue(collection, function() {

});
console.log(nums);

function displayValue(col, callback) {
  for(var i = 0; i < col.length; i++) {
    sleep(col[i] * 500, function() {
      console.log('Count: ' + col[i]);
      if (col[i] % 2 == 0) {
        nums.push(col[i]);
      }
    });
    callback();
  }
}

function sleep(time, callback) {
  var stop = new Date().getTime();
  while(new Date().getTime() < stop + time) {
      ;
  }
  callback();
}


我希望有人可以帮助我了解我在做什么错。

最佳答案

如果要在console.log(i)不确定的地方访问collection[i],您可能会更清楚地看到问题所在。

for循环中发生的事情是迭代数组并触发多个异步任务。循环完成后,i的值为2。i是一个可通过回调访问的封闭变量,但请记住此处的异步计时,在您的for循环完成后,所有needsImported回调都将被调用,因此,collection[2]是未定义的。要解决此问题,您可以删除索引并改用Array.forEach

function loopOrders(collection, callback) {
    var answersReturned = 0;
    collection.forEach(function(item, index) {
        needsImported(item.ordernumber, function(answer) {
            console.log('index:', index);
            if (answer) {
                OrdersListToImport.push(item);
            }
            if (++answersReturned == collection.length) {
                callback();
            }
        });
    });
}


还要注意,如果确实需要在回调中跟踪索引,则可以像上面一样在forEach回调中将其作为第二个参数接收。

还有一点说明:)此代码中有一个重大缺陷:

needsImported: function(ordernumber, callback) {
    pool.query('Select controlnumber From orders Where ordernumber = ?', [ordernumber], function(err, result) {
      if (!err) {
        if (result.length == 0) {
          callback(true);
        }
        else {
          callback(false);
        }
      }
    });
  }


如果确实出现了err,则您将忽略它,但更糟糕的是,您将不会调用回调。令人困惑的错误将由此产生。在node中,通常的做法是将err var作为回调的第一个参数,因此在成功的情况下,您可以执行此callback(null, true)

10-06 12:00