Reputation: 5246
I had an issue with values being assigned prior to an async call being complete, so I opted to use Promises (in this instance: Bluebird). Which I thought would solve the problem, but seeing as I'm not at all familiar with promises / or node for that matter, it's still doing the same thing.
How would I go about modifying my code below, to use promises correctly? And maintain a flow, so I can validate modules
based upon a previous row
?
var Promise = require('bluebird');
var db = require('../shared/db');
var queryHelper = require('../shared/queryHelper');
var schemas = require('../schemas/schemas');
var _ = require('lodash');
var serverSettings = require('../shared/coreServerSettings');
// Create new instance of mysql module
var connection = new db();
var queryhelper = new queryHelper();
// Promised methods
var queryAndWait = Promise.promisify(connection.query);
..snip..
queryAndWait(query + '; ' + queryFoundRows, params).then(function (result) {
var payload = [];
var site_access = [];
var module_access = [];
_.each(result[0], function (row) {
var sites = row.site_access.split(',');
_.each(sites, function (site_id) {
site_access.push(site_id);
});
row.site_access = site_access;
site_access = [];
queryAndWait(queryModules, [row.priv_id]).then(function (result) {
_.each(result, function (module) {
var modulePriv = {
priv_name: module.priv_name,
priv_num: module.priv_num,
enabled: module.enabled
};
module_access.push(modulePriv);
});
//console.log("am assigning " + JSON.stringify(module_access));
row.module_access = module_access;
module_access = []
});
payload.push(row);
});
});
To clarify:
Sorry, modules are groups of products that users (row) have access to, which are calculated on the fly (bitwise - hence no join available and a separate query), the module query returns something like the following, which I then loop through and attach to the row prior to returning the payload:
[{"priv_name":"INTERACT","priv_num":1,"enabled":1},{"priv_name":"STAFF_ADMIN","priv_num":32,"enabled":1},{"priv_name":"INT_EDIT","priv_num":64,"enabled":0},{"priv_name":"FAILED_LOGIN","priv_num":128,"enabled":0},{"priv_name":"INT_TAGS","priv_num":256,"enabled":0},{"priv_name":"NC","priv_num":512,"enabled":0},{"priv_name":"CC_TIMETABLE_MGR","priv_num":1024,"enabled":0}]
Upvotes: 1
Views: 127
Reputation: 1813
Promise help you to control de flow of the application in a simple way. I encourage you to read the basic principles about promise, at least the Promise A+ specification.
Your code could be written in many ways this is the way that I recommend because is modular:
var Promise = require('bluebird');
var queryAndWait = Promise.promisify(connection.query);
function getRows(params) {
return queryAndWait(query + '; ' + queryFoundRows, params)
.then(function (result) {
var site_access = [];
_.each(result[0], function (row) {
var sites = row.site_access.split(',');
_.each(sites, function (site_id) {
site_access.push(site_id);
});
row.site_access = site_access;
site_access = [];
return row;
});
});
}
function getModules(row) {
return queryAndWait(queryModules, [row.priv_id])
.then(function (result) {
var payload = [];
var module_access = [];
_.each(result, function (module) {
var modulePriv = {
priv_name: module.priv_name,
priv_num: module.priv_num,
enabled: module.enabled
};
module_access.push(modulePriv);
});
row.module_access = module_access;
payload.push(row);
return payload;
});
}
getRows(params)
.then(getModules)
.then(function(payload) {
// Do something with your payload
})
I did the next:
You can also manage the erros using the catch method of promises, for example:
getRows(params)
.catch(function(err) {
// Something went wrong with getRows
// If i can't recovery must return a reject.
})
.then(getModules)
.catch(function(err) {
//Something went wrong with getModules
// If i can't recovery must return a reject.
})
.then(function(payload) {
// Do something with your payload
})
Upvotes: 1
Reputation: 9330
yes, the inner queryAndWait
will run independently for each row as you don't chain the promises.
Since you use bluebird you'll need something like this to maintain the flow
queryAndWait(query + '; ' + queryFoundRows, params).then(function (result) {
return Promise.map(result[0], function (row) {
var site_access = [];
var module_access = [];
var sites = row.site_access.split(',');
_.each(sites, function (site_id) {
site_access.push(site_id);
});
row.site_access = site_access;
return queryAndWait(queryModules, [row.priv_id]).then(function (result) {
_.each(result, function (module) {
var modulePriv = {
priv_name: module.priv_name,
priv_num: module.priv_num,
enabled: module.enabled
};
module_access.push(modulePriv);
});
row.module_access = module_access;
return row;
});
});
}).then(function(payload) {
console.log(payload);
}).catch(function(error) {
console.log(error);
});
Upvotes: 1