2013-06-08 4 views
4

Мне нужно запросить строки из базы данных, обработать некоторую информацию в строке и затем обновить каждую строку с результатом.node.js: для каждого по строкам и асинхронно обновляется?

Это мой пример код, где намерение состоит в том, чтобы перебрать каждую строку и обновление метки:

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(){...}), и затем выполняется каждое ОБНОВЛЕНИЕ один за другим, и это будет нормально. Но чтобы помочь моему пониманию, я хотел бы знать, как я могу корректно выполнять обновления асинхронно.

ответ

4

Ваша row переменная является замыканием в функции обратного вызова. Функция обратного вызова не вызывается до тех пор, пока вы не зациклируете весь список результатов. Запросы 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', 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); 
     }); 
    }); 
    }); 
}); 
+0

извини, я хотел сказать, что я не хочу полагаться на любые модули. Не потому, что я анти-модули, а потому, что я хочу лучше понять, как писать код узла. Является '_.each (rows, function() {...})' any different to 'rows.forEach (function() {...}))'? – user2045006

+0

А, я понимаю, что вы сейчас говорите. Запросы работают. По какой-то причине в моем фактическом коде это не так, должно быть, это что-то другое. – user2045006