展平嵌套回调

时间:2012-04-20 13:55:45

标签: javascript node.js mongodb callback

我在学习使用Node.js中的回调编程风格时遇到了令人沮丧的问题。我有一个MongoDB数据库的查询。如果我传入一个函数来执行结果它可以工作,但我宁愿将其展平并让它返回值。任何有关如何正确执行此操作的帮助或指示表示赞赏。这是我的代码:

var getLots = function(response){
    db.open(function(err, db){
        db.collection('lots', function(err, collection){
            collection.find(function(err, cursor){
                cursor.toArray(function(err, items){
                    response(items);
                })
            })
        })
    })
}

我想要更像这样的东西:

lots = function(){
    console.log("Getting lots")
    return db.open(openCollection(err, db));
}

openCollection = function(err, db){
    console.log("Connected to lots");
    return (db.collection('lots',findLots(err, collection))
    );
}

findLots = function(err, collection){
    console.log("querying 2");
    return collection.find(getLots(err, cursor));
}

getLots = function(err, cursor) {
    console.log("Getting lots");
    return cursor.toArray();
}

最终的数据集将通过函数调用重新启动。

问题是我收到Node.js的错误,说错误未定义或未定义集合。出于某种原因,当我嵌套回调时,正确的对象被传递下来。当我尝试这种扁平的风格时,它会抱怨事情没有定义。我不知道怎么让它传递必要的物品。

2 个答案:

答案 0 :(得分:4)

您需要的是通过npm为节点提供的许多control flow libraries之一,并在Node.js wiki上编目。我的具体建议是caolan/async,你可以使用async.waterfall函数来完成这种类型的流程,其中每个异步操作必须按顺序执行,每个都需要前一个操作的结果。

伪代码示例:

function getLots(db, callback) {
   db.collection("lots", callback);
}

function findLots(collection, callback) {
    collection.find(callback);
}

function toArray(cursor, callback) {
    cursor.toArray(callback);
}

async.waterfall([db.open, getLots, find, toArray], function (err, items) {
    //items is the array of results
    //Do whatever you need here
    response(items);
});

答案 1 :(得分:0)

async是一个很好的流量控制库。 Frame.js提供了一些特定的优点,例如更好的调试,以及更好的同步函数执行安排。 (虽然它目前在npm中并不像async那样)

以下是Frame中的内容:

Frame(function(next){
    db.open(next);
});
Frame(function(next, err, db){
    db.collection('lots', next);
});
Frame(function(next, err, collection){
    collection.find(next);
});
Frame(function(next, err, cursor){
    cursor.toArray(next);
});
Frame(function(next, err, items){
    response(items);
    next();
});
Frame.init();