How to query mysql before starting http server in nodejs

1.4k views Asked by At

A simple question, I use nodejs for HTTP restful API service. Now I want query some mysql data before http server start, the code snippet:

var price = -1;  
var userId = 'some user provided value';  
var sql    = 'SELECT max(price) FROM users WHERE id = ' + connection.escape(userId);  
connection.query(sql, function(err, results) {  
  price = results.price;  
});

server = http.createServer(function (request, response) {  
      handler(request);   //response depend on price
}).listen(8012); 

So how to combine mysql query and http server code?

2

There are 2 answers

2
cptroot On

You just add the server inside of the return callback for the connection query, like so:

var price = -1;  
var userId = 'some user provided value';  
var sql    = 'SELECT max(price) FROM users WHERE id = ' + connection.escape(userId);  
connection.query(sql, function(err, results) {  
  price = results.price;  
  server = http.createServer(function (request, response) {  
    console.log(price);
    handler(request, price, response);   //response depend on price
  }).listen(8012); 
});
2
Darren White On

Although this is a simple question the size of the answer is huge! Tim Ruffles gave a whole lecture on the subject at the London Node Users Group this week (July 2013) which is available as a video lecture [http://www.youtube.com/watch?v=nHXKA82M-LY].

The problem here is the fundamental one of how to handle something that needs to be done synchronously (in sequence) while working in an asynchronous (no order guaranteed) programming environment.

Of the list of ways Tim uses to deal with this problem there are three which seem to be able to help you here.

As suggested in other posts, you could use a callback from your code:

var price = -1;  
var userId = 'some user provided value';  
var sql    = 'SELECT max(price) FROM users WHERE id = ' + connection.escape(userId);  
connection.query(sql, function(err, results) {  
  price = results.price;  
  //start the server afer the sql connection has called back
  server = http.createServer(function (request, response) {  
      handler(request);   //response depend on price
  }).listen(8012); 
});

However this leads to what is called 'pyramid code' and can become unmanageable quite quickly.

My personal preference to solve this problem would be to use the async library [https://github.com/caolan/async]which contains an arsenal of tools for dealing with sequencing problems in node. I choose this because it seems the most intuitive way to me.

var async = require('async');

functon query(callback){
var price = -1;  
var userId = 'some user provided value';  
var sql    = 'SELECT max(price) FROM users WHERE id = ' + connection.escape(userId);  
connection.query(sql, function(err, results) {  
  price = results.price;  
  callback();
});

}

    function boot(callback){
    server = http.createServer(function (request, response) {  
          handler(request);   //response depend on price 
           callback();
    }).listen(8012); 
    }

    async.series([query,boot]);

You can install async with npm install async.

Or the third approach that might reasonably be used for this problems is to use promises. These are well accepted, by while learning node coming from a language other javascript, I found this quite hard to adapt to coming from a language other then javascript, but programmers who use JQuery seem to favour this approach. There is a tutorial of how use promises in node.js here : http://howtonode.org/promises

Tim of course provides a much more in-depth analysis and comparison in his lecture of these approaches and supplies a few insights of how we might do this in the future.

You might also find the modules Express, Restify and Restler useful as a way to create a Restful api.

*disclaimer I haven't run this code as I don't have mysql installed - opportunity for an edit here :)