链接异步函数Node.js bluebird mongoskin

时间:2015-06-13 17:42:32

标签: javascript node.js asynchronous promise bluebird

我一直在阅读很多关于如何链接异步函数的帖子,但我似乎无法正确使用它!

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

我有对象用户:

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

我如何将其链接以具有以下算法:

 start:
      for each account:
           fetchDataForAccount
      Finally:
           Send Response 

1 个答案:

答案 0 :(得分:3)

您的算法可以使用以下代码实现:

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 而不是使用延续(例如回调)。你可以使用蓝鸟惊人的promisification能力来做到这一点:)我们在mongo.Collection.prototype使用它,这样当调用collection()时,它将返回一个支持promise的集合实例。然后我们fetchAccountData 返回 aggregateAsync返回的承诺,以便客户端知道该承诺何时解决。

接下来,我们会在帐户中映射每个帐户并返回一个承诺,该承诺将在提取帐户数据已分配给帐户对象后实现。然后我们使用Promise.all,它将返回一个履行的承诺"当数组中的所有项目都满足时#34; (来自文档)。

最后,我们必须使用then()来"等待"直到从all返回的promise已经解决,并且最终用完整的用户对象发回响应。