Использование Q с Node-Mysql
Я относительно новичок в Node, но у меня был хороший успех с портированием через RESTful API, что ранее было сделано в PHP. Взаимодействие с базами данных происходит довольно часто, и в результате я оказался в том, что многие считают "пирамидой гибели" из-за асинхронной природы Node.
В результате я пытаюсь выполнить обещания с использованием библиотеки Q, но пока не добился большого успеха и все еще получаю нулевые наборы результатов, когда считаю, что должен получать данные. Ниже приведена моя текущая структура перед добавлением Q. Если бы кто-нибудь мог посоветовать, как правильно реализовать Q для этого, я мог бы выполнить этот пример и преобразовать остальные вызовы базы данных / memcached в эту модель.
// helper function to get a company row
getRow = function(lookUp, callback) {
var query = db.query('SELECT * FROM table WHERE lookUp = ?', lookUp, function(err, result) {
var count = Object.keys(result).length;
if(count == 0) {
return;
} else {
callback(null, result);
}
});
}
// function that uses the above helper method
insertItem = function(request, response) {
var data = JSON.parse(request.body.data);
var message = data.message;
var lookUp = data.lookUp;
security.verifyToken(lookUp, function (lookUpError) {
if (lookUpError) {
var errorResult = { "response": "error", "msg": lookUpError };
response.json(errorResult);
response.end();
} else {
getRow(lookUp, function (companyError, row) {
var companyId = row[0].id;
var res = helper.insertFeedItem(companyId, message, function (insertError, insertResult) {
var result = (feedError) ? { "response": "error", "msg": insertError} : insertResult;
response.json(result);
response.end();
});
});
}
});
}
То, что я хотел бы сделать, это сделать что-то вроде:
var result = getCompanyRow(lookUp);
companyId = result.company_id;
Опять же, любое понимание того, как наилучшим образом реализовать Q (или просто обещания в целом) для этого случая, будет чрезвычайно ценно.
* РЕДАКТИРОВАТЬ:
Вот то, что я пытался реализовать Q, но, как я уже сказал, я ничего не получаю.
function getRow(id) {
var dfd = Q.defer();
var query = db.query('SELECT * FROM table WHERE lookUp = ?', id, function(err, result) {
if(err) { dfd.reject(err); }
else { dfd.resolve(result); }
});
return dfd.promise;
}
Вышеупомянутое не работает вообще, когда вызывается как result = getRow (id); Я попытался использовать Q.all и привязать функцию к этому, но я также ничего не получил при попытке такого подхода. Я не был уверен, что включить в мой вызов.then(), но я попробовал несколько вещей, но ни одна из них не увенчалась успехом.
1 ответ
Ваш getRow
Функция обещания выглядит многообещающе:-) Ее можно еще больше упростить, используя методы адаптера узла изQ
:
function getRow(id) {
return Q.nfcall(db.query, 'SELECT * FROM table WHERE lookUp = ?', id);
// ^^^^^^^^^^^^^^^^^^^^
// or .ninvoke(db, "query", … if it must be called as a method
}
// or even just
var getRow = Q.nbind(db.query, db, 'SELECT * FROM table WHERE lookUp = ?');
Я не вижу никакой пользы от использования.then (function...), потому что он все еще требует вложения, как и обратный вызов.
Преимущество (помимо упрощенной обработки ошибок) состоит в объединении нескольких задач, то есть когда security.verifyToken
а также helper.insertFeedItem
методы будут возвращать обещания. Если они этого не делают (и вы не можете их изменить), вы все равно можете использовать Q.nfcall
как в примере выше. Предполагая, что они сделали, ваш код может быть упрощен до
function insertItem(request, response) {
var data = JSON.parse(request.body.data);
security.verifyToken(data.lookUp).then(function(/* no lookupError */) {
return getRow(data.lookUp); // potentially catch SQL errors here
}).then(function(row) {
return helper.insertFeedItem(row[0].id, data.message);
// What was the `res` it had returned before?
}).catch(function(someError) { // lookUpError, companyError, insertError
return { "response": "error", "msg": someError };
}).done(function(result) {
response.json(result);
response.end();
});
}