2014-01-22 2 views
3

Я относительно новичок в Node, но у меня был хороший успех с портированием RESTful API, который ранее выполнялся на PHP. Существует довольно много взаимодействия с базами данных, и в результате я нашел себя в том, что, как я считаю, многие называют «пирамидой гибели» из-за асинхронности Node.Использование Q с Node-Mysql

В результате я беру удар по реализации обещаний с использованием библиотеки 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 (или только обещает в целом) для этого случая будет чрезвычайно оценен.

* EDIT:

Вот что я пытался до сих пор для реализации 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; 
} 

Вышеупомянутое не работает вообще, когда вызывается как результат = getRow (id); Я попытался использовать Q.all и привязал функцию к этому, но при попытке этого подхода я также ничего не получил. Я не был уверен, что включить в мой призыв к .then(), но я пробовал несколько вещей, ни один из них не был успешным.

+0

«getRow», который, возможно, никогда не назовет его «обратным вызовом», - это плохая идея, даже без обещаний. По крайней мере, выполните обратный вызов (nothingFoundError) ' – Bergi

+0

Не могли бы вы также показать нам ваш подход к использованию обещаний? – Bergi

+0

@ Bergi Добавлено. Очень грубо, я знаю, но это все, что я оставил после нескольких раундов проб и ошибок. –

ответ

4

Ваше getRow функция обещание выглядит многообещающе :-) Это может быть дополнительно упрощается за счет использования node adapter methods from 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 (функция .. .), поскольку он все еще требует вложенности, как и обратный вызов.

Выгода (кроме облегчения обработки ошибок) происходит из цепочки нескольких задач, то есть когда и ваши 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(); 
    }); 
}