2

好吧,我认为如果我只是复制我的整个 node.js 路由会更容易,这样你就可以看到我在说什么。

我正在尝试对我的 MongoDB 数据库进行多个查询(每天一个)。查询运行良好,但是当他们触发回调时,我的增量变量已经增加了。

所以为此:

exports.graph = function(req, res) {

  function pad(num, size) {
    var s = num+"";
    while (s.length < size) s = "0" + s;
    return s;
  }

  database.collection('customerData', function(err, collection) {

    for (var i = 2; i < 18; i++) {

      sDay = pad(i, 2);
      eDay = pad(i + 1, 2);

      collection.find({ 
        DATE: { 
          $gte: sDay + 'APR13:00:00:00',
          $lt: eDay + 'APR13:00:00:00' 
        }
      }, function(err, cursor){
        cursor.toArray(function(err, data){
          var counter = 0;
          for (var point in data) {
            trans = parseInt(data[point].Total_Transaction * 100);
            counter += trans;
          }

          console.log(i, counter / 100);  
        });
      });
    }
  });
}   

我得到这个输出:

18 22023.29
18 24483.03
18 22644.11
18 23194.31
18 21560.99
18 23024.32
18 24384.93
18 23138.34
18 24400.63
18 28418.6
18 31691.65
18 31111.62
18 42358.74
18 38355.76
18 36787.52
18 42870.19
18 22023.29
18 22644.11
18 24483.03
18 23194.31
18 21560.99
18 23024.32
18 24400.63
18 23138.34
18 24384.93
18 28418.6
18 31691.65
18 31111.62
18 42358.74
18 38355.76
18 36787.52
18 42870.19

这(显然)并不理想 - 数字不一定按照查询被触发的顺序返回,所以对我来说弄清楚哪些去哪里很重要。

我想不出一种方法以一种有意义的方式将我的算术结果存储在查询回调中,以便以后可以使用它。

有什么想法吗?

4

2 回答 2

2

附带说明,与您的示例和下面的示例不同,您确实应该保存集合引用,而不是在每次需要使用它时重新实例化它。

至于您的问题,只需将每个调用的逻辑包装在其自己的函数中即可。这样你就可以创建一个闭包,它会记住每个特定查询的日期。下面我创建了一个示例,将所有结果放入一个对象中,然后当所有查询完成后,它会按顺序输出所有结果。

var _outstanding = 0,
    _results = {};

database.collection('customerData', function(err, collection) {
  for (var i = 2; i < 18; i++) {
    _outstanding++;
    getDay(collection, i, getDayCallback);
  }
});

function getDay (collection, day, callback) {
  sDay = pad(day, 2);
  eDay = pad(day + 1, 2);

  collection.find({ ...query obj... }).toArray(err, data) {
    var counter = 0;
    if (!err) {
      for (var point in data)
        counter += parseInt(data[point].Total_Transaction * 100);
    }

    callback(err, day, counter);
  });
}

function getDayCallback (err, day, count) {
  // ...actually handle any errors, of course...
  _results[day] = count;

  if (--_outstanding === 0) { //display the results in-order when done
    for (var i = 2; i < 18; i++)
      console.log(i, _results[i] / 100)
  }
}

在这个人为的例子中,getDay可以getDayCallback很容易地组合成一个函数,但在现实世界中,您很可能希望它们保持分开。另外,不知道从哪里来218但我猜它们实际上不应该像我一样被多次硬编码:)。

于 2013-05-12T04:56:28.320 回答
1

@Bret 的回答是 100% 正确的。

我想贡献一点来展示如何通过最少的修改来转换代码以包含闭包。由于闭包在这种情况下(经常发生)非常有用,如果可能有助于了解这种模式。

exports.graph = function(req, res) {

    function pad(num, size) {
        var s = num+"";
        while (s.length < size) s = "0" + s;
        return s;
    }

    database.collection('customerData', function(err, collection) {

        for (var i = 2; i < 18; i++) {

            sDay = pad(i, 2);
            eDay = pad(i + 1, 2);

            collection.find({ 
                DATE: { 
                    $gte: sDay + 'APR13:00:00:00',
                    $lt: eDay + 'APR13:00:00:00' 
                }
            }, (function(i){ //anonymous function which is sync-executed, bringing
                             // 'i' to closure-scope.
                return function(err, cursor){
                    cursor.toArray(function(err, data){
                        var counter = 0;
                        for (var point in data) {
                            trans = parseInt(data[point].Total_Transaction * 100);
                            counter += trans;
                        }

                        console.log(i, counter / 100);  
                    });
                });
            }(i))
        }
    });
}
于 2013-05-12T14:21:30.427 回答