我对异步编程有点新意。我遇到了需要在循环中执行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()函数这样的东西,但该函数的行为是什么?它之后的代码会立即继续,还是等待循环完成?
答案 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)