我想按顺序执行查询,但我不知道什么是最好的方法。
假设我想做以下事情:
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);
}
}
}
答案 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();
}
}