javascript - Chaining Asynchronous Functions Node.js bluebird mongoskin -
i have been reading many posts on how chain asynchronous functions can't seem right!
as title indicates. trying chain mongoskin database calls together, can gather information in chunks , send accumulated result in response.
i have object user :
var user = { username: 'someusername', accounts: [{name: 'account_1'}, {name: 'account_2'}] }
for each of accounts need gather data , send accumulated data in response. using following loop iterate on accounts:
var promise = require('bluebird'); var db = require('mongoskin').db('mongodb://localhost/somedb'); for(var x in user.accounts){ //fetch account data user.accounts[x].accountdata = fetchaccountdata(user.accounts[x].name); } //finally send collected response response.send(user);
and function fetchaccountdata looks following:
function fetchaccountdata(screen_id){ db.collection('master') .aggregate([ {$match: {screen_id: screen_id}} ], function(err, res){ if(err) return null; else{ console.log('done', screen_id); return res; } }); }
how can chain have following algorithm:
start: each account: fetchdataforaccount finally: send response
your algorithm can achieved using following code:
var promise = require('bluebird'); var mongo = require('mongoskin'), db; promise.promisifyall(mongo.collection.prototype); db = mongo.db('mongodb://localhost/somedb'); promise.all(user.accounts.map(function(acct) { return fetchaccountdata(acct.name).then(function(data) { acct.accountdata = data; }); })) .then(function() { response.send(user); }) .catch(function(err) { // handle error }); function fetchaccountdata(screen_id){ return db .collection('master') .aggregateasync([ {$match: {screen_id: screen_id}} ]); }
edit: here's breakdown of code
the first thing need ensure aggregate
returns promise instead of using continuation (e.g. callback). can using bluebird's amazing promisification abilities :) here use on mongo.collection.prototype
when collection()
called return promise-capable collection instance. have fetchaccountdata
return promise returned aggregateasync
client has way of knowing when promise resolved.
next, map on each account in accounts , return promise fulfilled once account data fetched and has been assigned account object. use promise.all return promise fulfilled "when items in array fulfilled" (from docs).
finally, have use then()
"wait" until promise returned has resolved, , send response complete user object.
Comments
Post a Comment