Reputation: 62
I have a server file with a switch using the URL to display appropriate content. One of the cases is /users which should display a JSON string of a certain table. This is returned from a mysql file.
server.js
var http = require('http')
var url = require('url')
var port = 8080
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname
console.log('Request for ' + pathname + ' received.')
response.writeHead(200, {'Content-Type': 'text/html'})
response.write(run(pathname))
response.end()
}
function run(pathname) {
switch(pathname) {
case '/':
response = 'Welcome to my little test'
break
case '/time':
response = 'The time is ' + new Date().toLocaleTimeString()
break
case '/users':
var response
require('./mysql').getUsers(function(users) {
console.log(users)
response = users
})
return response
break
default:
response = 'Unable to locate the requested page'
}
return response
}
http.createServer(onRequest).listen(port)
console.log('Server started on port ' + port + '.')
mysql.js
var mysql = require('mysql')
var connection = mysql.createConnection({
user: "root",
password: "password",
database: "main"
})
exports.getUsers = function(callback) {
connection.query('SELECT * FROM users;', function (error, rows, fields) {
callback(JSON.stringify(rows));
});
};
The console.log(users)
in server.js displays the JSON string fine, but I cannot figure out how to get the value out of the callback and into the response variable.
Any ideas will be greatly appreciated.
Upvotes: 1
Views: 4738
Reputation: 1314
You do not need to serialize the mysql returned rows
to use it. Either you can process it within getUsers
, or return it back to the controller. If you return it, change code to:
exports.getUsers = function(callback) {
connection.query('SELECT * FROM users;', function (error, rows, fields) {
callback(rows);
});
};
Now within the server.js
file, you can process the returned rows, like:
case '/users':
var response = ''
require('./mysql').getUsers(function(users) {
for (var i in users) {
var user = users[i];
var userId = user.id;
var userName = user.user_name;
response += "User - ID: "+userId+" Name: "+userName+"\n";
}
})
return response;
break;
You can process
Upvotes: 0
Reputation: 1147
you can't do it like this. the problem is easy. let's talk about it:
function getUsers
is an asynchronous. so the code follow runs like this:
case '/users':
var response
require('./mysql').getUsers(function(users) {
console.log(users)
response = users
})
return response
break
first, run require('./mysql').getUser()
, then it will do return response
directly, then break
. when the getUser
function is finished, it will run
function(users) {
console.log(users)
response = users
})
so, a rule you need to follow: once you use asynchronous, the other function have to be asynchronous. i wonder you can modify like follow:
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname
console.log('Request for ' + pathname + ' received.')
response.writeHead(200, {'Content-Type': 'text/html'})
run(pathname, function(res){ response.write(res)}) //changed
response.end()
}
function run(pathname, callback) {
switch(pathname) {
case '/':
callback('Welcome to my little test')
break
case '/time':
callback('The time is ' + new Date().toLocaleTimeString())
break
case '/users':
var response
require('./mysql').getUsers(function(users) {
console.log(users)
callback(users) # changed
})
break
default:
callback('Unable to locate the requested page')
}
}
http.createServer(onRequest).listen(port)
console.log('Server started on port ' + port + '.')
Upvotes: 0
Reputation: 3488
The way you could extract the value out of the callback is to assign that value to a variable out of the callback's scope, but I don't recommend you to do that since you would end up with lots of global variables, besides you don't know when the variable will be assigned. Try this and see what happens so you get some insight with how callbacks and node.js works:
function run(pathname) {
switch(pathname) {
case '/':
response = 'Welcome to my little test'
break
case '/time':
response = 'The time is ' + new Date().toLocaleTimeString()
break
case '/users':
var response
var out_of_callback_users
require('./mysql').getUsers(function(users) {
out_of_callback_users = users
console.log("In the callback")
console.log(users)
response = users
})
console.log("After require");
console.log(out_of_callback_users) //Users have not been assigned yet
setTimeout(function(){
console.log("In the timeout")
console.log(out_of_callback_users)
},5000) //After 5 secs the query has been completed and users have been assigned.
return response
break
default:
response = 'Unable to locate the requested page'
}
return response
}
The way I would go is something like this:
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname
console.log('Request for ' + pathname + ' received.')
response.writeHead(200, {'Content-Type': 'text/html'})
run(pathname, function(response){
response.write(response)
response.end()
})
}
function run(pathname,cb) {
switch(pathname) {
case '/':
cb('Welcome to my little test');
break;
case '/time':
cb('The time is ' + new Date().toLocaleTimeString());
break;
case '/users':
require('./mysql').getUsers(function(users) {
console.log(users);
cb(users);
})
break;
default:
cb('Unable to locate the requested page');
}
return;
}
http.createServer(onRequest).listen(port)
console.log('Server started on port ' + port + '.')
Upvotes: 2