I'm attempting to create a final array with data pulled from 3 functions. The first two functions have all the data but then the 3rd function needs to run looping through one of the fields from function 2 in order to have the complete array at the end.
I'm looking for some advice and examples on how to fix this and or do it better. I have been advised promises would be a good solution, but could someone throw together a quick example so I can better get my head around it?
In my services controller I have this as the page here and checks if the user is logged in.
exports.all = function(req, res){ if (!req.isAuthenticated()){ res.redirect('login'); } else {
It uses the services database schema in the model to connect to the database and pull out the info I need:
Database .find() .exec(function (err, services) { if (err) { return console.log(err); } if (!services) { console.log('Failed to load any Services'); }
Once the services are found (multiple RPC/API services that have the same commands but different data returned), I async through each and connect.
async.mapSeries(services, function(service, cb) { connect(service); client.getBalance(req.user._id, 6, function(err, balance) { console.log(balance); if (err) balance = "Offline"; client.getAddressesByAccount(req.user._id, function(err, address) { console.log(address); if (err) address = "Offline";
Once the first two lots of data is returned (the first is just a string number and the second is an array of addresses then for each address I want too async again and run a third command and then map the result of each to the corresponding address from above and output a final array to pass to the view.
if(address != "Offline") { async.mapSeries(address, function (item, callback){ // print the key client.cmd('getreceivedbyaddress', item, 6, function(err, addressrecevied) { if (err) console.log(err); console.log(item + " = " + addressrecevied); // console.log(JSON.stringify(addressrecevied, null, 4)); }); callback(); // tell async that the iterator has completed }, function(err) { console.log('iterating done'); }); }; // console.log(service.abr + " address = " + address); console.log(service.abr + " balance = " + balance);
Callback that outputs the current top two results to the view variables:
return cb(null, { name: service.name, display: service.display, address: address, balance: balance, abr: service.abr, }); }); });
Function to call the view and pass variables when done:
}, function(err, services) { // console.log(services); if (err) { return console.log(err); } req.breadcrumbs('Services', '/services/all'); res.render('services/index', { title: 'Services', icon: 'iconfa-cog', summary: 'Services information', services: services, path : req.path, breadcrumbs: req.breadcrumbs(), udata : req.session.user }); }); }); } }
Work in progress
exports.all = function(req, res){
if (!req.isAuthenticated()){
res.redirect('login');
} else {
Wallet
.find()
.exec(function (err, wallets) {
if (err) {
return console.log(err);
}
if (!wallets) {
console.log('Failed to load any Wallets');
}
async.mapSeries(wallets, function(coin, cb) {
//
// Q FUNCTION START
//
function getServiceBalance(service) {
connect(service);
cmd = Q.denodeify(client.cmd.bind(client)),
getBalance = Q.denodeify(client.getBalance.bind(client)),
getAddressesByAccount = Q.denodeify(client.getAddressesByAccount.bind(client));
client.getBalance(req.user._id, 6, function(err, balance) {
console.log("Service: " + service.name + " - Balance: " + balance);
if (err) balance = "Offline";
});
// We're going to fill this in step by step...
var result = {
name: service.name,
display: service.display,
abr: service.abr
};
return getBalance(req.user._id, 6)
.then(function (balance) {
result.balance = balance;
console.log("Balance:" + balance);
console.log("User ID: " + req.user._id);
return getAddressesByAccount(req.user._id);
})
.then(function (addresses) {
result.address = addresses;
console.log("Addresses:" + result.address);
if (!_.isArray(addresses)) {
// Throwing errors inside `then` is fine: they will get caught in `catch` below
throw new Error('Could not get addresses array');
}
// For each address, call getreceivedbyaddress and gather results in array
return Q.all(_.map(addresses, function (address) {
return cmd('getreceivedbyaddress', address, 6);
}));
}).then(function (addressesReceived) {
result.addressReceived = addressesReceived;
}).catch(function (err) {
// Here's the catch method--the *one and only* place all errors propagate to.
console.log(err);
result.balance = 'Offline';
result.address = 'Offline';
result.addressReceived = 'Offline';
}).thenResolve(result);
}
exec().then(function (services) {
if (!services) {
throw new Error('Failed to load any Services');
}
return Q.all(_.map(services, getServiceBalance), function (serviceBalances) {
req.breadcrumbs('Services', '/services/all');
res.render('services/index', {
title: 'Services',
icon: 'iconfa-cog',
summary: 'Services information',
services: serviceBalances,
path : req.path,
breadcrumbs: req.breadcrumbs(),
udata : req.session.user
});
});
}).done();
//
// Q FUNCTION END
//
});
});
}
}