2016-11-26 49 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