node.js按顺序查询数据库

时间:2015-07-07 21:51:32

标签: node.js synchronous

我想按顺序执行查询,但我不知道什么是最好的方法。

假设我想做以下事情:

if (name) {
  //first query
  db.query({name:name}).exec(function(err,result) {
  //save result
  })
}
if (isEmpty(result)) {
  //make another query
  db.query({anotherField:value}).exec(function(err,result) {
  //save result
  })
}

我应该在这种情况下使用承诺吗?

这将是cakePHP的一个例子:

if (!isset($field1)) {
  $result = $this->item->find( ... conditions => ... = $field2);
} else {
  if (!isset($field2)) {
    $result = $this->item->find( ... conditions => ... = $field1);
  } else {
    $result = $this->item->find( ... conditions => ... = $field1 && ... =$field2);
    if (empty($result)) {
      $result = $this->item->find( ... conditions => ... =$field2);
    }
  }  
}

2 个答案:

答案 0 :(得分:2)

Promise非常适合这种情况,q库是最常见的。您可能只想嵌套您的承诺:

var q = require('q');

if (name) {
  //first query
  q.ninvoke(db.query({name:name}), 'exec')
  .then(function(result) {
    //save result
    if (isEmpty(result)) {
      //make another query
      q.ninvoke(db.query({anotherField:value}), 'exec')
      .then(function(result) {
        //save result
      })
      .fail(function(err) {
        //handle failure
        console.error(err, err.stack);
      });
    }
  })
  .fail(function(err) {
    //handle failure
    console.error(err, err.stack);
  });
}

q.ninvoke允许我们将标准nodejs函数转换为它们的等效承诺。

答案 1 :(得分:2)

如果您的意思是“按顺序”,您可以嵌套回调。传递回调是构造异步代码的经典(非承诺)方式:

function doMultipleAsyncThings(name, callback){
  if (name) {
    //first query
    db.query({name:name}).exec(function(err,result) {
      if (isEmpty(result)) {
        //make another query
        db.query({anotherField:value}).exec(function(err,result) {
          //save result
        })
      } else {
        //save result
      }
    })
  } else {
    return callback('no name');
  }
}

抬头,经过2次以上的操作后,你最终会在'回调地狱'中使用100多行嵌套代码,async库对此有帮助:

var async = require('async');
doMultipleAsyncThings('plato', function(){
  console.log(arguments)
});

function doMultipleAsyncThings(name, callback){
  // `callback` is a passed-in function to call after doMultipleAsyncThings is done
  // Here, it is the function we passed in above after 'plato'
  async.waterfall([function(done){
      done(null, name);
    },
    firstQuery,
    secondQuery,
  ], callback)
}

function firstQuery(name, done){
  if (name) {
    // You can define and pass a callback inline:
    db.query({name:name}).exec(function(err,result) {
      done(err, result);
    })
  } else {
    done('no name');
  }
}

function secondQuery(result, done){
  if (isEmpty(result)) {
    // You can pass a callback by reference:
    db.query({anotherField:value}).exec(done)
  } else {
    //save result
    done();
  }
}