2014-03-06 23 views
1

在實施承諾得到這個代碼:Q.js變量傳遞並行流

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-------------------------------+ 

任何建議表示讚賞

回答

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

感謝您的關注。我會嘗試這個解決方案。 – Schtz

+0

工作得很好,謝謝 – Schtz

2

你可以簡單地將其嵌套:

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

+0

'spread(function(data,cupr){return {data:data,uupr:uupr,cupr:cupr};'''''''''''''' ('{data:data,uupr:uupr,cupr:cupr}')。怎麼會這樣?'uupr'永遠不會被傳遞到任何地方 – Schtz

+0

@Schtz:很好,你在代碼中設置'uupr = entry',嵌套版本只能在範圍內使用。忘記更改變量名稱,謝謝。 – Bergi