今天在用mongodb和express中做博客时,教程中提到了对于mongodb的操作及回调的过程是典型的深度嵌套回调,代码如下
结构就清晰了很多,看起来一目了然.
Post.getOne = function(name, day, title, callback) {
mongodb.open(function (err, db) {
if (err) { ... }
db.collection('posts', function (err, collection) {
if (err) { ... }
collection.findOne({ ... }, function (err, doc) {
if (err) { ... }
collection.update({ ... }, function (err) {
mongodb.close();
callback( ... );
});
});
});
});
};
这里的函数每层都是相互依赖,上一级操作的结果会传到下一级,这是我们就可以利用async里面的waterfall来解决深度嵌套的问题.
在这里结合github上的官方文档做一下翻译和总结.
waterfall(tasks, [callback])
首先,waterfall中的第一个参数tasks是一个函数数组,每一个函数的参数都取自上一个参数的回调函数传递下来的参数,如果早这个过程中,发生了错误,那么waterfall会直接调用callback,将错误传递进去,之后tasks数组中的函数就不会被调用了.参数
----tasks 一个函数数组,每个函数传递一个callback(err,result1,result2,...).第一个参数是一个error(可以为空),之后的参数会被当作下一个task的参数传递下去.
----callback(err,[result]) 这是一个当所有函数执行完成之后的一个可选择的回调.最后一个task中的结果会传递给这个回调.
使用waterfall,上面的代码就可以改写成如下格式:
async.waterfall([
function(cb){
pool.acquire(function (err, db) {
cb(err,db);
});
},
function(db,cb){
db.collection('users',function(err,collection){
cb(err,collection,db);
});
},
function(collection,db,cb){
collection.insert(user,{safe:true},function(err,user){
cb(err,user,db);
});
}
],function(err,user,db){
pool.release(db);
callback(err,user.ops[0]);
})
结构就清晰了很多,看起来一目了然.
另外,task数组还可以传递函数名,像这样
async.waterfall([
myFirstFunction,
mySecondFunction,
myLastFunction,
], function (err, result) {
// result now equals 'done'
});
waterfall的用法大致就是这样,以后用到了async中的其他方法,会再来补充