Reputation: 695
I'm trying to avoid callback hell by breaking down my Express / Kraken.js controller into smaller callback functions.
I was processing a request and had about 6 levels of nested anonymous callback functions.
so now I have my main function that looks like this:
// ugh, I know this isn't right
var globalProducts = {};
module.exports = function (server) {
server.get('/project', function (req, res) {
var data = req.query;
globalData = data;
if(!data.projectId || !data.ruleSetId)
res.json({error: "Incomplete input data."});
// pass response to products call back
Project.findOne({ _id: mongoose.Types.ObjectId(data.projectId) }, setUpProducts);
});
};
function setUpProducts(err, project){
// get all products and pass them down the pipe
project.findAllChildren(setUpRules);
}
function setUpRules(err, products) {
// we need to access products in another function
globalProducts = products;
// find the rule set and build the rule Flow
RuleSet.findOne({ _id: mongoose.Types.ObjectId(globalData.ruleSetId) }, function(err, ruleSet) {
ruleSet.buildFlow(processFlow);
});
}
My question is what is the best way to pass around info between callbacks ? My solution was var globalProducts = {};
but to me, the controller contain any 'global state' .. whats the best way to handle this ?
Upvotes: 0
Views: 788
Reputation: 13570
Doing this is a bad idea. It will cause race condition type issue — basically it's the same as sharing data in multithreaded environment. Instead you can use req
or res
to store data. To do that you need them in scope, so you can define all functions inside route handler or make each function a middleware so it will have req
and res
as arguments. Here is an example of this approach:
function check (req, res, next) {
if(!req.query.projectId || !req.query.ruleSetId) return res.json({error: "Incomplete input data."});
next()
}
function findProject (req, res, next) {
Project.findOne({ _id: mongoose.Types.ObjectId(req.query.projectId) }, after);
function after (err, project) {
if (err) return next(err);
req.project = project;
next();
}
}
function findProducts (req, res, next) {
req.project.findAllChildren(after)
function after (err, products) {
if (err) return next(err);
req.products = products;
next();
}
}
function respond (req, res) {
res.render('view', {
products : req.products,
project : req.project
});
}
module.exports = function (server) {
server.get('/project', check, findProject, findProducts, respond);
};
Upvotes: 3