我可以在不深度嵌套代码的情况下执行许多异步数据库请求吗?

时间:2011-11-13 21:59:10

标签: node.js asynchronous coffeescript

我对异步编程有点新意。我遇到了需要在循环中执行8次数据库查找的情况。我不知道如何实现这一点 - 我的数据库库在回调函数中返回数据,在我有所有8行之前我无法继续使用我的代码,所以我需要暂停直到所有8个查找都完成。

这就是我现在想的那样:

db.world.Queue.find(@user.kingdom.troops_queue).on 'success', (troops_queue) ->
    db.world.Queue.find(@user.kingdom.tanks_queue).on 'success', (tanks_queue) ->
        #etc etc

这当然很糟糕,但是我想不出一种方法可以将它卷成一个循环,允许我的代码暂停,只有在最后一个项目被填满时才会继续。我正在研究像jQuery的.each()函数这样的东西,但该函数的行为是什么?它之后的代码会立即继续,还是等待循环完成?

5 个答案:

答案 0 :(得分:9)

有两种常用的方法。第一个是使用像caolans async这样的库:

async.parallel
  a: (cb) -> doTaskA cb
  b: (cb) -> doTaskB cb
, (err, {a, b}) ->
  # you can use err, a and b here now

第二种方法是streamlinejs

troops_queue = db.world.Queue.find(@user.kingdom.troops_queue).on 'success', _
tanks_queue = db.world.Queue.find(@user.kingdom.tanks_queue).on 'success', _
# go on here

但是,两个解决方案都假设回调的第一个参数是错误 - 如果不是这样,你应该对你用来更改它的库的作者进行错误。

答案 1 :(得分:1)

使用after.js

等流量控制
var data = {};
    cb = after(8, function ( ) {
        // handle all 8 results
    }),
    queue = db.world.Queue,
    kingdom = this.user.kingdom;

queue.find(kingdom.troops_queue).on('success', function (result) {
    data["troops_queue"] = result;
    cb();
});

// etc

P.S。我为你修好了那份咖啡。

答案 2 :(得分:1)

您可以按“成功进展”顺序组织查询;这个序列可以被延续式循环使用,有点像Javascript:

var lookups = [
   function(){ Q.find(@user.kingdom.troops_queue; },
   function(troops_queue){ Q.find(...tanks_queue; },
   function(tanks_queue){ Q.find(...next_queu; },
   ....
];

这个“分层”序列可以通过异步工厂来实现,如

function proceedOn( sequence, previous_result ) {       
   var first = sequence[0];
   first( previous_result ).onSuccess( function(result){
     proceedOn( sequence[1..], result );
   } );
}

proceedOn( lookups );

(我在阵列语法糖上采取了一些诗意的自由)

答案 3 :(得分:1)

我总是使用Step作为我的项目,它非常干净漂亮。

这是一个连续回调的例子:

Step(
  function readSelf() {
    fs.readFile(__filename, this);
  },
  function capitalize(err, text) {
    if (err) throw err;
    return text.toUpperCase();
  },
  function showIt(err, newText) {
    if (err) throw err;
    console.log(newText);
  }
);

你可能也想做一些并行的东西,然后才触发回调,幸运的是this.parallel()就是这样的:

Step(
  // Loads two files in parallel
  function loadStuff() {
    fs.readFile(__filename, this.parallel());
    fs.readFile("/etc/passwd", this.parallel());
  },
  // Show the result when done
  function showStuff(err, code, users) {
    if (err) throw err;
    console.log(code);
    console.log(users);
  }
)

答案 4 :(得分:0)

由于您使用“coffescript”标记了一些链接,您可以检查(长线程!): issue241issue287issue350issue1710(可能更多......)

简而言之: