链接异步函数 Node.js bluebird mongoskin
Chaining Asynchronous Functions Node.js bluebird mongoskin
我已经阅读了很多关于如何链接异步函数的文章,但我似乎无法正确理解它!
如标题所示。我正在尝试将 mongoskin 数据库调用链接在一起,以便我可以分块收集所有信息,然后最终在响应中发送累积结果。
我有 object 用户:
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
您的算法可以使用以下代码实现:
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
return 是 Promise 而不是使用延续(例如回调)。您可以通过使用 bluebird 的惊人 promisification 能力来做到这一点 :) 这里我们在 mongo.Collection.prototype
上使用它,这样当调用 collection()
时它将 return 一个具有 promise 能力的集合实例。然后我们有 fetchAccountData
return return 由 aggregateAsync
编辑的承诺,因此客户端有办法知道该承诺何时得到解决.
接下来,我们映射 accounts 中的每个帐户和 return 一旦获取帐户数据就会履行的承诺 并且 它已分配给帐户目的。然后我们使用 Promise.all 这将 return 实现的承诺 "when all the items in the array are fulfilled" (来自文档)。
最后,我们必须使用 then()
到 "wait" 直到 promise returned from all 已经解决,最后用完整的用户对象发回响应。
我已经阅读了很多关于如何链接异步函数的文章,但我似乎无法正确理解它!
如标题所示。我正在尝试将 mongoskin 数据库调用链接在一起,以便我可以分块收集所有信息,然后最终在响应中发送累积结果。
我有 object 用户:
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
您的算法可以使用以下代码实现:
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
return 是 Promise 而不是使用延续(例如回调)。您可以通过使用 bluebird 的惊人 promisification 能力来做到这一点 :) 这里我们在 mongo.Collection.prototype
上使用它,这样当调用 collection()
时它将 return 一个具有 promise 能力的集合实例。然后我们有 fetchAccountData
return return 由 aggregateAsync
编辑的承诺,因此客户端有办法知道该承诺何时得到解决.
接下来,我们映射 accounts 中的每个帐户和 return 一旦获取帐户数据就会履行的承诺 并且 它已分配给帐户目的。然后我们使用 Promise.all 这将 return 实现的承诺 "when all the items in the array are fulfilled" (来自文档)。
最后,我们必须使用 then()
到 "wait" 直到 promise returned from all 已经解决,最后用完整的用户对象发回响应。