node.js async call inside other function
Problem
I've got quite silly questions, i'm trying to make redirection service using node.js based on conditions pulled from mongodb... so code lookis like that:
var http = require('http'),
util = require('util'),
url = require('url');
var server = http.createServer(function(req, res) {
domain = req.headers['host'];
var url = getRedirect(domain);
res.writeHead(301, { 'Location': url});
res.end();
});
server.listen(8080);
var getRedirect = function(domain) {
Domain.findOne({ 'name': domain }, 'url', function (err, domain) {
if (err) return handleError(err);
console.log('redirect url %s.', domain.url)
return domain.url
})
}
Of course - doesn't work as it should be, because Domain.findOne is finding results with delay, and return doesn't assign resuluts to url... I tried to pass "res" object into getRedirect function but i'm pretty sure that it's wrong.
Any clues?
Solution
You'll need to use a callback for this, since (as you've pointed out), the domain/url fetching is asynchronous. The node convention is to use an "error first callback" signature.
Try this:
var http = require('http'),
util = require('util'),
url = require('url');
var server = http.createServer(function(req, res) {
var domain = req.headers['host'];
// provide a callback to getRedirect so we can get the value asynchronously
getRedirect(domain, function(err, url) {
if (err) return handleError(err);
res.writeHead(301, { 'Location': url });
res.end();
});
});
server.listen(8080);
var getRedirect = function(domain, cb) {
Domain.findOne({ 'name': domain }, 'url', function (err, domain) {
if (err) return cb(err);
console.log('redirect url %s.', domain.url);
// instead of returning, pass the result to the callback
cb(null, domain.url);
});
};
Discussion
View additional discussion.