Использование 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();
    });
}
Другие вопросы по тегам