扁平化嵌套回调函数

4

我在学习使用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收到一个错误,说err未定义或者collection未定义。由于某种原因,当我嵌套回调时,正确的对象会被传递下去。但是,当我尝试使用这种扁平化的风格时,它会抱怨一些东西未定义。我不知道如何让它传递必要的对象。


2
你提供的示例解决方案有什么具体问题? - Matt Gibson
看起来是个好主意,实现也不错。有什么问题吗? - mellamokb
1
你也可以尝试这个:https://github.com/caolan/async,专门为此类问题而创建。 - freakish
请使用以下链接查看:https://github.com/lm1/node-fibers-promise - ControlAltDel
问题在于我从Node.js得到一个错误,说err未定义或集合未定义。由于某种原因,当我嵌套回调时,正确的对象被传递下来。当我尝试转换为扁平化风格时,它会抱怨一些东西未定义。我不知道如何传递必要的对象。我已经在这个问题中添加了这个评论。对于我的含糊不清表示抱歉。 - Matthew Crews
2个回答

4
你需要的是通过npm安装并在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);
});

实际上,async.series 不会将参数传递给下一个调用。需要使用 async.waterfall - freakish
当我使用这个函数时,生成的数据集是否会传递回上层并返回给调用函数?我希望从这一系列回调中返回 cursor.toArray() 函数的结果。 - Matthew Crews
查看异步文档。使用waterfall,每个函数的回调值都作为参数传递给链中的下一个函数,最终函数的回调值作为参数传递给“done”回调函数。您可以根据需要链接结果。我会更新我的答案,包括一个示例。 - Peter Lyons

0

async是一个很好的流程控制库。Frame.js提供了一些特定的优势,比如更好的调试和更好的同步函数执行安排。(尽管它目前不像async那样在npm上)

以下是在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();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接