链接asynchronous函数Node.js bluebird mongoskin

我一直在阅读很多关于如何链接asynchronous函数的文章,但我似乎无法做到这一点!

正如标题所示。 我试图将mongoskin数据库调用链接在一起,以便我可以将所有信息以块的forms收集,然后最终将响应中的累积结果发送出去。

我有这样的对象用户:

var User = { username: 'someusername', accounts: [{name: 'account_1'}, {name: 'account_2'}] } 

对于每个帐户,我需要收集数据,然后在响应中发送累积的数据。 所以我使用以下for循环遍历帐户:

 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 the collected response response.send(user); 

而fetchAccountData函数如下所示:

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

我如何链接这个有以下algorithm:

  start: for each account: fetchDataForAccount Finally: Send Response 

你的algorithm可以使用下面的代码来实现:

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

编辑:这是代码的细分

你需要做的第一件事是确保aggregate返回一个Promise而不是使用延续(例如callback)。 你可以使用蓝鸟的惊人promisification能力:)这里我们在mongo.Collection.prototype上使用它,所以当调用collection()时,它将返回一个具有promise能力的集合实例。 然后我们有fetchAccountData返回由aggregateAsync 返回的诺言,所以客户端有一个知道何时该诺言被解决的方法。

接下来,我们映射到账户中的每个账户,并返回一旦提取账户数据并将其分配给账户对象时将履行的承诺。 然后,我们使用Promise.all ,它将返回一个“当数组中的所有项目都满足时”(来自文档)的promise。

最后,我们必须使用then()来“等待”,直到所有返回的promise都解决了,最后用完整的用户对象返回响应。