Pregunta

While implementing promises got this code:

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)})
    }
)

Its work can be described by a diagram:

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

I've used external variables uupr and cupr to store data from first .then calls.

So I have two problems:

1) Avoid using external variables.

2) rearrange code to get alternative flow diagram.

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

Any advice is appreciated

¿Fue útil?

Solución

Try something along the lines of this pseudo-code:

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()

Otros consejos

You can simply nest them:

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)})
});

Now, to let the toArray not wait for the getUserData result, just do those in parallel:

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)})
});

(Using invoke instead an explicit then)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top