Как запросить MySQL перед запуском http-сервера в nodejs
Простой вопрос, я использую nodejs для службы HTTP restful API. Теперь я хочу запросить некоторые данные MySQL перед запуском http-сервера, фрагмент кода:
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);
Итак, как совместить запрос MySQL и код http-сервера?
2 ответа
Хотя это простой вопрос, размер ответа огромен! Тим Раффлс прочитал целую лекцию на эту тему в Лондонской группе пользователей узлов на этой неделе (июль 2013 года), которая доступна в виде видеолекции [http://www.youtube.com/watch?v=nHXKA82M-LY].
Проблема здесь заключается в том, как обрабатывать что-то, что необходимо делать синхронно (последовательно) при работе в среде асинхронного (без порядка) программирования.
Из списка способов, которые Тим использует для решения этой проблемы, есть три, которые могут вам здесь помочь.
Как предлагается в других постах, вы можете использовать обратный вызов из вашего кода:
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);
});
Однако это приводит к так называемому "коду пирамиды" и может довольно быстро стать неуправляемым.
Мое личное предпочтение для решения этой проблемы - использовать асинхронную библиотеку [https://github.com/caolan/async]wich, которая содержит арсенал инструментов для решения проблем секвенирования в узле. Я выбираю это, потому что это кажется мне наиболее интуитивным способом.
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]);
Вы можете установить async с помощью npm install async.
Или третий подход, который может быть разумно использован для решения этих проблем, заключается в использовании обещаний. Они хорошо приняты, поскольку, изучая ноды, исходящие из языка, отличного от javascript, я обнаружил, что это довольно трудно приспособить к переходу с языка, отличного от javascript, но программисты, которые используют JQuery, похоже, одобряют этот подход. Здесь вы найдете руководство по использованию обещаний в node.js: http://howtonode.org/promises
Тим, конечно, дает гораздо более глубокий анализ и сравнение в своей лекции об этих подходах и дает несколько идей о том, как мы могли бы сделать это в будущем.
Вы также можете найти модули Express, Restify и Restler полезными в качестве способа создания API Restful.
* Отказ от ответственности Я не запускал этот код, так как у меня не установлен mysql - возможность для редактирования здесь:)
Вы просто добавляете сервер внутри обратного обратного вызова для запроса соединения, например:
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);
});