4

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

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

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,这样就可以了。但为了帮助我理解,我想知道如何正确地异步执行更新。

4

1 回答 1

6

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

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

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);
      });
    });
  });
});
于 2013-06-08T23:31:04.523 回答