如何格式化mysql查询以使用异步/ promsies?

时间:2017-06-10 23:06:43

标签: mysql node.js asynchronous callback promise

我尝试使用2个参数对我的数据库进行简单查询,并且我无法使用Promises / Async重新格式化此代码以避免回调地狱。这是代码:

module.exports = {
  getDailyRaw: function(school, meal, callback) {
     var sql = "SELECT * FROM daily WHERE school = ? AND meal = ?";
     pool.getConnection(function(err, conn) {
         if(err) { console.log(err); callback(true); return; }
         conn.query(sql, [school, meal], function(err, results) {
             conn.release();
             if(err) { console.log(err); callback(true); return; }
             callback(false, school, results);
         })
     })
  }, ....

我一直在努力查找有关修复此问题的教程,但尚未能够正确实施/理解它们。

编辑:我现在正在使用' promise-mysql'库可以完成工作,但我仍然无法将多个查询链接在一起。我如何将已建立的连接传递给另一个语句,以便我可以再次调用查询? 更新的代码:

getDaily: function(school, meal, callback) {
    pool.getConnection().then(function(conn) {
        var sql = "SELECT * FROM daily WHERE school = ? AND meal = ?";
        return conn.query(sql, [school,meal]);
    }).then(function(rows) {
        var qMarks = "";
        var foodNames = [school];
        rows.forEach(function(item) {
            foodNames.push(item.name);
            qMarks += "?,";
        });
        qMarks = qMarks.substring(0, qMarks.length - 1);
        var sql = "SELECT * FROM foods WHERE school = ? AND name IN (" + qMarks + ")";
        return conn.query(sql, foodNames);
    }).then(function(finalData) {
        callback(finalData);
    }).catch(function(err) {
        callback(null);
        console.log(err);
    })
},

2 个答案:

答案 0 :(得分:0)

有多种方法可以将链接.then()中的变量提供给链中的某个位置。您可以在How to Chain and Share Prior Results with Promises

中查看这些选项的摘要

对于这种特殊情况,我建议像这样嵌套:

getDaily: function(school, meal, callback) {
    pool.getConnection().then(function(conn) {
        var sql = "SELECT * FROM daily WHERE school = ? AND meal = ?";
        return conn.query(sql, [school,meal]).then(function(rows) {
            var qMarks = "";
            var foodNames = [school];
            rows.forEach(function(item) {
                foodNames.push(item.name);
                qMarks += "?,";
            });
            qMarks = qMarks.substring(0, qMarks.length - 1);
            var sql = "SELECT * FROM foods WHERE school = ? AND name IN (" + qMarks + ")";
            return conn.query(sql, foodNames);
        }).then(function(finalData) {
            callback(finalData);
        });
    }).catch(function(err) {
            callback(null);
            console.log(err);
    });
},

而且,最好只是一起摆脱回调并返回承诺并让调用者使用承诺。然后,如果调用者想要将这种异步操作与其他人同步,那么它已经使用了一个承诺让他们更容易:

getDaily: function(school, meal) {
    return pool.getConnection().then(function(conn) {
        var sql = "SELECT * FROM daily WHERE school = ? AND meal = ?";
        return conn.query(sql, [school,meal]).then(function(rows) {
            var qMarks = "";
            var foodNames = [school];
            rows.forEach(function(item) {
                foodNames.push(item.name);
                qMarks += "?,";
            });
            qMarks = qMarks.substring(0, qMarks.length - 1);
            var sql = "SELECT * FROM foods WHERE school = ? AND name IN (" + qMarks + ")";
            return conn.query(sql, foodNames);
        });
    }).catch(function(err) {
        console.log(err);
        throw err;
    });
},

注意:如果您要返回承诺并希望在.catch()中记录错误,则必须重新抛出错误,以确保仍然拒绝返回的承诺(就像使用try / catch一样)

答案 1 :(得分:0)

您可以通过同步执行程序nsynjs以顺序方式编写和执行逻辑。它逐步运行代码,自动暂停承诺并等待其解决,然后再进行下一步。代码如下所示:

    Private Sub DataGridProductsDesign() 'Procedimento que contem o novo estilo da datagrid
        tabelaprodutos.DataMember = "Produtos" 'Nome da tabela associada no datagrid
        tabelaprodutos.ReadOnly = False 'Coloca o datagrid apenas para leitura
        Dim GridStyle As New DataGridTableStyle 'Cria um novo estilo do datagrid
        GridStyle.MappingName = "Produtos" 'Associa a relacao da tabela clientes com a da base de dados
        Dim referenciaCol As New DataGridTextBoxColumn 'define a variavel do tipo DataGridTextBoxColumn
        referenciaCol.MappingName = "Referencia" 'atribui um campo da tabela
        referenciaCol.HeaderText = "Referencia" 'atribui um nome à coluna
        referenciaCol.Width = 110 'define tamanho coluna
        GridStyle.GridColumnStyles.Add(referenciaCol) 'adiciona coluna
        Dim descricaoCol As New DataGridTextBox
        descricaoCol.MappingName = "descricao"
        descricaoCol.HeaderText = "Descricao"
        descricaoCol.Width = 210
        GridStyle.GridColumnStyles.Add(descricaoCol)
        Dim precoCol As New DataGridTextBoxColumn
        precoCol.MappingName = "preco"
        precoCol.HeaderText = "Preco"
        precoCol.Width = 110
        GridStyle.GridColumnStyles.Add(precoCol)
        Dim quantidadeCol As New DataGridTextBoxColumn
        quantidadeCol.MappingName = "quantidade"
        quantidadeCol.HeaderText = "Qauntidade"
        quantidadeCol.Width = 110
        GridStyle.GridColumnStyles.Add(quantidadeCol)
        Dim disponivelCol As New DataGridTextBoxColumn
        disponivelCol.MappingName = "disponivel"
        disponivelCol.HeaderText = "Disponivel"
        disponivelCol.Width = 110
        GridStyle.GridColumnStyles.Add(disponivelCol)

    End Sub