我在几个网页上抓桌子并用表格中的项目更新MYSQL数据库。我正在使用MYSQL模块,并在循环遍历所有行时遇到各种错误。这是函数的一次迭代:
var connection = mysql.createConnection(opts);
connection.connect();
function updateDB(o,lang){
var tbl_name = "news_"+lang;
o.forEach(function(entry,index,arr){
var sql1 = "SELECT * FROM "+tbl_name+" WHERE url = '"+htmlencode.htmlEncode(entry.url)+"' and omit = '1'";
connection.query(sql1, function(err, rows, fields) {
connection.end();
if (err){
console.log("can't run query=" + sql1 +"\n Error="+err);
}
else{
console.log('ROWS:',rows);
// if rows.length = 0 then update table with new info here...
}
});
});
};
如果我注释掉connection.end()行,这实际上是有效的,但是连接永远不会结束,并且进程永远保持活着。我将它作为批处理脚本运行,所以我需要它优雅地结束。在connection.end()到位后,我得到"Cannot enqueue Quit after invoking quit."
我尝试使用async.series将connection.end
置于最终回调中,但仍然无效。我尝试使用池和不同的代码迭代来尝试使某些东西起作用。我最后使用mysql模块并想知道是否还有另一个可以更好地工作。
答案 0 :(得分:0)
看起来您只有一个连接而且您正在使用.forEach
,这不是异步友好的。
您应该使用连接池和async.eachLimit
来控制并发。
var pool = mysql.createPool({
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASS,
database: process.env.MYSQL_NAME,
connectionLimit: 10
});
function updateDB(o,lang){
// submit as a sub-function to get the `lang` closure
// this could probably be organized a different way, but this fits your structure
function submit(entry, callback) {
var tbl_name = "news_"+lang;
var sql = [
'SELECT * FROM ' + tbl_name,
' WHERE url="?" and omit="1"'
].join('');
pool.getConnection(function(err, connection) {
if(err) return callback(err);
connection.query(sql, [entry.url], function(err, results) {
connection.release();
if(err) return callback(err);
console.log('ROWS:',results);
});
});
}
async.eachLimit(o, 10, submit, function(err) {
if(err) throw err;
console.log('Done processing');
});
}
即使您不需要多个连接,也应该几乎总是使用池。池将根据需要重新创建连接。这非常方便,因为您的连接可能会因mysql超时,网络问题和任何其他原因而死亡。当您使用池时,您的代码将更加健壮。
如果您只想一次执行一个查询,只需将第二个参数更改为async.eachLimit
为1
。