node.js同步调用收集结果

时间:2015-06-27 13:24:49

标签: node.js sqlite

我有一张表,其中人员被保存了他们活跃的时间(以秒为单位)。 我想编写一个函数来收集另一个名为gather的表中的总时间。

对于每一行,我正在检查gather表中的条目是否存在。根据该结果,我进行插入或更新。

db.serialize(function() {
    db.each("SELECT * from TEST", function(err, row) {
        db.get("SELECT * from GATHER where name = " + row.name "", function(err, row) {
            if(row === undefined || row === null){
                var stmt = db.prepare("INSTER INTO gather (name, time) VALUE(?,?)");
                stmt.run([name, seconds], function(error){
                    console.log('lastInsert ' + this.lastID);
                }); 
                stmt.finalize();
            }else{
                seconds += row.time;//increment time
                var stmt = db.prepare("UPDATE gather SET time = ? WHERE name = ?");
                stmt.run([seconds, row.name], function(error){
                    console.log('lastInsert ' + row.idProcessed);
                }); 
                stmt.finalize();
            }
        });
    });
});

我遇到的问题是sqlite以异步方式运行。因此,虽然应更新行,但在gather表中创建了多个条目。

同步运行此功能的正确方法是什么?我应该限制线路并每秒调用一次功能还是有智能的方式?

2 个答案:

答案 0 :(得分:2)

您可以使用async。例如(但首先你应该阅读最后的最后笔记):

var async = require('async');

var data = {}

var yourFirstSelect() = function(callback){
  //You do your first select 
  //...
  db.get("SELECT * from TEST", function(err, row) {
    if(row){
      data.name = row.name;
      data.otherInterestingAttribute = row.otherInterestingAttribute;
      callback(err, data);
    }else{
      callback('Row is null');
    }
  })
  //..
}

var yourSecondSelect() = function(data, callback){
  //You do your second select 
  //...
   db.get("SELECT * from GATHER where name = " + data.name "", function(err, row) { //Note that I'm using data instead of row
    if(row){
      data.seconds = row.seconds;
      data.otherInterestingAttribute = row.otherInterestingAttribute;
      callback(err, data);
    }else{
      callback('Row is null');
    }
  })
  //..
}

var decide() = function(data, callback){
  if (data.somethingExists) { //Do your validations
    data.type = 'update';
    callback(err, data);
  } else {
    data.type = 'insert';
    callback(err, data);
  }
}

var update() = function(data,callback){
  if (data.type === 'update') {
    //...
    //Do your stuff in order to update
    seconds += row.time;//increment time
      var stmt = db.prepare("UPDATE gather SET time = ? WHERE name = ?");
          stmt.run([seconds, row.name], function(error){
            console.log('update ' + row.idProcessed);
          }); 
      stmt.finalize();
    //...
  } else {
    callback(err,data);
  }
}

var insert() = function(data,callback){
  if (data.type === 'insert') {
    //...
    //Do your stuff in order to insert
    var stmt = db.prepare("INSTER INTO gather (name, time) VALUE(?,?)");
        stmt.run([data.name, data.seconds], function(error){
          console.log('lastInsert ' + this.lastID);
          callback(err,data);
        }); 
        stmt.finalize();
    //...
  } else {
    callback(err,data);
  }
}

var niceWorkflow = function(){
  async.waterfall([
      yourFirstSelect,
      yourSecondSelect,
      decide,
      update,
      insert
  ],
  function (err, result) {
    console.log('Done');
  })
}

//and call your workflow
niceWorkflow();

当然,这不是100%正常工作的代码,我写的是为了让你看起来另一种方式来做你正在尝试的事情。许多变量,验证和更多只是示例,我故意忘记了db.each,以避免过于夸张和混淆你,并试图回答你的最后一个问题Is there a smarter way?

答案 1 :(得分:0)

您也可以使用Q library中的Q.all。 在所有承诺得到解决后,它将返回一个承诺。一个承诺失败,然后Q.all将被拒绝。