2016-11-26 22 views
0

目标:制作多个MySQL调用

我试图让使用这样一个查询的结果作为“mysql的”模块中的Node.js多个SQL查询输入下一个语句。

sql1 = SELECT id FROM users WHERE email=? // get user id from email 
val1 = [email protected] 

sql2 = SELECT something FROM profiles WHERE user_id=? 
val2 = user_id // result of sql1 

做法:

我使用的是JS “承诺” 来实现这一目标:

var run_query = function(conn,sql){ 

return new Promise(function (fulfill, reject){ 

    conn.query(sql, val, function(err, res) { 

     if(err) reject(err); 
     else fulfill(res); 

    }); 

}); 

} 

var conn = db.config(mysql); 

run_query(conn,[ 'SELECT id FROM users WHERE email=?' , ['[email protected]'] ]).then(function(result){ 

    console.log(result.id); // result of 1st query 

    return run_query(conn,[ 'SELECT something FROM profiles WHERE user_id=?' , [result.id] ]); 

}).then(function(result){ 

    console.log(result.something); // result of 2nd query 

}).catch(function(err){ 

    console.log('there was an error', err); 

}); 

conn.end(); 

问题:

首届查询返回正确的结果,但第二个查询从mysql模块中引发以下错误:

Error: Cannot enqueue Query after invoking quit. 
~blah blah blah~ 
code: 'PROTOCOL_ENQUEUE_AFTER_QUIT', fatal: false 

我试图解析:

我相信这事做多次调用被制成,而连接是打开和conn.end();被称为最后。我把它移动了一下,但没有奏效。

我试图打开多个语句mysql的模块

var conn = mysql.createConnection({multipleStatements: true}); 

..但没有工作要么。

如何用JS承诺结构使用mysql节点模块?

+0

您可能想要使用类似[Sequelize](http://docs.sequelizejs.com/en/v3/)的支持开箱即用的承诺,而不是将自己的包装破解在一起。 – tadman

回答

2

您使用的是承诺,但承诺代码是同步的,而外部代码是异步的。所以conn.end在第二个查询之前运行。

使用conn.end秒。然后块内像这样 和删除外conn.end

var conn = db.config(mysql); 

run_query(conn,[ 'SELECT id FROM users WHERE email=?' , 
['[email protected]'] ]).then(function(result){ 

console.log(result.id); // result of 1st query 

return run_query(conn,[ 'SELECT something FROM profiles WHERE 
user_id=?' , [result.id] ]); 

}).then(function(result){ 

    console.log(result.something); // result of 2nd query 
    conn.end(); 
}).catch(function(err){ 

    console.log('there was an error', err); 

}); 
+1

翻译:“嘿,MySQL,你可以做这个查询,还有一些其他的东西取决于它吗?哦,当你这样做时,你现在可以关闭连接吗?”在完成之前,你正在把这个东西拉上去。 – tadman

+0

我现在看到我的方式的错误 – yevg

0

承诺明确是用来写干净的代码,但你正在做的正好相反。

什么Himanshu说是正确的,你的conn.end()首先执行。鉴于你的用例,我建议你使用Async模块​​。浏览一次可用的功能。

我认为Async.series将服务你的权利,虽然有多个异步功能,可以帮助你的情况下,特别是队列。

async.series([ 
    function(callback) { 
    //Your First SQL Query based on response send success or failure callback 
     callback(null, 'one'); 
    }, 
    function(callback) { 
    //Your Second SQL Query based on response send success or failure callback 
     callback(null, 'two'); 
    } 
], 
// optional callback 
function(err, results) { 
    //listen to results from your codes and put some logic based on what you want and close the connection here 
conn.close(); 
}); 

怀疑:你为什么要一个接一个地执行它们?

+0

甘道夫白,他的诺言语法是正确的。不需要使用async.series,他可以通过承诺来完成。你可以说async.series是完成这项工作的另一种方法。 –

+0

代码看起来很干净,我从来没有说他的语法错了吗?再次阅读。而且,人们的确提出了更好的解决SO问题的方法。我希望你知道这一点。 –

+0

为什么代码不干净?我有一个promise函数和一个.then链。我已经实现了一个像你之前发布的异步版本,但重点是使用一个查询的结果作为另一个查询的输入。这样做异步没有意义,因为你没有可靠的第一个结果 – yevg