Cou*_*les 4 asynchronous node.js node-mysql
我需要从数据库中查询行,每行处理一些信息,然后用结果更新每一行。
这是我的示例代码,其意图是遍历每一行并更新标签:
var mysql = require('mysql');
var db = mysql.createConnection(config.database);
db.connect(function() {
db.query('SELECT id FROM testTable', function (err, rows) {
if (err) {
console.log(err);
} else {
if (rows.length) {
for (var i = 0, len = rows.length; i < len; i++) {
var row = rows[i];
console.log(row);
var label = "Label_"+row.id;
db.query('UPDATE testTable SET label = ? WHERE id = ?', [label, row.id], function(err, result) {
if (err) {
console.log(err);
} else {
console.log("Set label on row %s", row.id);
}
})
}
}
}
})
});
Run Code Online (Sandbox Code Playgroud)
输出为:
{ id: 1 }
{ id: 2 }
{ id: 3 }
{ id: 4 }
Set label on row 4
Set label on row 4
Set label on row 4
Set label on row 4
Run Code Online (Sandbox Code Playgroud)
因此,如您所见,我更新了第4行四次,而不是每次更新四行。虽然我新提出的查询将是非阻塞的,但我认为每个值都会改变。
我知道我可以更改要使用的代码rows.forEach(function(){...}),然后依次执行每个UPDATE,这样就可以了。但是,为了帮助我理解,我想知道如何正确地异步执行更新。
您的row变量是回调函数中的闭包。在遍历所有结果列表之前,不会调用回调函数。sql查询是正确的,但是在每次回调中打印出row.id的值只会给您每次for循环的最后一次迭代,因为那是每个回调的关闭状态。
您可以通过使用下划线模块来避免这种情况。它还可以帮助您简化逻辑。
npm install underscore
Run Code Online (Sandbox Code Playgroud)
然后您的代码将如下所示:
var mysql = require('mysql');
var _ = require('underscore');
var db = mysql.createConnection(config.database);
db.connect(function() {
db.query('SELECT id FROM testTable', function (err, rows) {
if (err) { console.log(err); return; }
_.each(rows, function(one) {
console.log(one);
var label = "Label_"+one.id;
var sql = 'UPDATE testTable SET label = ? WHERE id = ?';
db.query(sql, [label, one.id], function(err, result) {
if(err) { console.log(err); return; }
console.log("Set label on row %s", one.id);
});
});
});
});
Run Code Online (Sandbox Code Playgroud)