node.js:对于每个行和更新asynchronous?

我需要从数据库查询行,每行处理一些信息,然后用结果更新每一行。

这是我的示例代码,其目的是循环遍历每一行并更新标签:

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 

所以,正如你所看到的,我已经更新了第四行四次而不是四行一次。 虽然我新查询将是非阻塞的,我认为值会改变每一个。

我知道我可以改变我的代码使用rows.forEach(function(){...}) ,然后执行每个更新一个接一个,那就没事了。 但为了帮助我的理解,我想知道我可以如何正确地执行更新asynchronous。

你的rowvariables是callback函数中的一个闭包。 callback函数不会被调用,直到你遍历所有的结果列表。 sql查询是正确的,但是在每个callback中打印出row.id的值只是给你每次for循环的最后一次迭代,因为这是每个callback的闭包状态。

您可以通过使用下划线模块来避免这种情况。 它也可以帮助你使逻辑更简单。

 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', 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); }); }); }); });