我需要从数据库中查询行,每行处理一些信息,然后用结果更新每一行.
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); } }) } } } }) });
这个输出是:
{ 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
所以,正如你所看到的,我已经将第4行更新了四次,而不是每次更新四行.虽然我新的查询将是非阻塞的,但我认为每个查询的值都会发生变化.
我知道我可以更改我的代码以使用rows.forEach(function(){…}),然后逐个执行每个UPDATE,这样就可以了.但为了帮助我理解,我想知道如何异步地正确执行更新.
解决方法
您的行变量是回调函数中的闭包.在循环遍历所有结果列表之前,不会调用回调函数. SQL查询是正确的,但是在每个回调中打印出row.id的值只会给你每次for循环的最后一次迭代,因为这是每次回调的闭包状态.
您可以使用underscore模块来避免这种情况.它还可以帮助您简化逻辑.
npm install underscore
然后你的代码看起来像这样:
var MysqL = require('MysqL'); var _ = require('underscore'); var db = MysqL.createConnection(config.database); db.connect(function() { db.query('SELECT id FROM testTable',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,one.id],result) { if(err) { console.log(err); return; } console.log("Set label on row %s",one.id); }); }); }); });