【问题标题】:Q.js variables passing in parallel flowsQ.js 变量在并行流中传递
【发布时间】:2014-04-08 15:34:41
【问题描述】:

在实现 promise 时得到了这个代码:

var MongoClient = require('mongodb').MongoClient
MongoClient.connect(db_uri, function(err, db) {
    if(err) throw err;
    var ccoll = db.collection('cdata');
    app.locals.dbstore = db;
}
var json= {}
//Auth is a wrapped mongo collection
var Auth = app.locals.Auth;
var coll = app.locals.dbstore.collection('data');
var ucoll = app.locals.dbstore.collection('udata');
var ccoll = app.locals.dbstore.collection('cdata');
var Q = require('q');
//testing with certain _id  in database
var _id = require('mongodb').ObjectID('530ede30ae797394160a6856');
//Auth.getUserById = collection.findOne()
var getUser = Q.nbind(Auth.getUserById, Auth);
//getUserInfo gives a detailed information about each user
var getUserInfo = Q.nbind(ucoll.findOne, ucoll);
var getUserData = Q.nbind(ccoll.findOne, ccoll);
//"upr" is a group of users
//getUsers gives me a list of users, belonging to this group
var getUsers = Q.nbind(ucoll.find, ucoll);
//Auth.getUserById = collection.find()
var listUsers = Q.nbind(Auth.listUsers, Auth);
var uupr = {}
var cupr = {}
getUserInfo({_id:_id})

    .then(function(entry){
        console.log('entry:', entry);
        uupr = entry;
        var queue = [getUsers({upr:entry.name}), getUserData({_id:entry._id})]
        return Q.all(queue);
    }
)
    .then(function(array2){
        console.log('array2:', array2);
        cupr = array2[1]
        var cursor = array2[0]
        var cfill =  Q.nbind(cursor.toArray, cursor);
        return cfill();
    }
)
    .then(function(data){
        json = {data:data, uupr:uupr, cupr:cupr}
        console.log('json:', json)
        res.render('test', {json : JSON.stringify(json)})
    }
)

它的工作可以用一张图来描述:

getUserInfo()==>(entry)--+-->getUsers()=====>array2[0]--+-->populate user list===>data--->render
                         |                              |
                         +-->getUserData()==>array2[1]--+

我使用外部变量 uuprcupr 来存储来自第一次 .then 调用的数据。

所以我有两个问题:

1) 避免使用外部变量。

2) 重新排列代码以获得替代流程图。

 getUserInfo()==>(entry)--+-->getUsers()==>usersList-->populate user list==>usersData-+->render
                          |                                                           |
                          +-->getUserData()====>uprData-------------------------------+

感谢任何建议

【问题讨论】:

    标签: node.js mongodb promise q


    【解决方案1】:

    您可以简单地嵌套它们:

    getUserInfo({_id:_id})
    .then(function(entry){
        console.log('entry:', entry);
        return Q.all([
          getUsers({upr:entry.name}),
          getUserData({_id:entry._id})
        ]);
        .spread(function(cursor, cupr) {
            console.log('array2:', [cursor, cupr]);
            return Q.ninvoke(cursor, "toArray")
            .then(function(data){
                return {data:data, uupr:entry, cupr:cupr};
            });
        });
    }).then(function(json) {
        console.log('json:', json)
        res.render('test', {json: JSON.stringify(json)})
    });
    

    现在,让toArray 不等待getUserData 结果,只需并行执行:

    getUserInfo({_id:_id})
    .then(function(entry){
        console.log('entry:', entry);
        return Q.all([
          getUsers({upr:entry.name}).invoke("toArray"),
          getUserData({_id:entry._id})
        ]);
        .spread(function(data, cupr) {
            return {data:data, uupr:entry, cupr:cupr};
        });
    }).then(function(json) {
        console.log('json:', json)
        res.render('test', {json: JSON.stringify(json)})
    });
    

    (使用invoke 代替显式then

    【讨论】:

    • spread(function(data, cupr) {return {data:data, uupr:uupr,cupr:cupr}; 你传递了 2 个参数(datacupr)并返回其中的 3 个({data:data, uupr:uupr, cupr:cupr})。怎么会这样? uupr 永远不会被传递到任何地方
    • @Schtz:不错!您在代码中设置了uupr = entry,在我的嵌套版本中,它仅在范围内可用。忘记改变量名了,谢谢。
    【解决方案2】:

    尝试一下这个伪代码:

    getUserInfo().then(function(userInfo) {
        return Q.all([
            userInfo,
            getUsers(... userInfo ...).then(convert to array),
            getUserData(... userInfo ...)
        ])
    }).spread(function(userInfo, usersArray, userData) {
        res.render(...)
    }, function(err) {
        handle the error
    }).done()
    

    【讨论】:

    • 感谢您的关注。我会试试这个解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多