2013-12-11 3 views
0

Я хочу обобщить данные, которые производятся асинхронно (в node.js). Как бы вы сделали это в потоковом режиме?Как накапливать асинхронные данные?

Например,

function test(){ 
    var accumulator = 0; 
    for(int i= 0; i<100; i++){ 
    // non blocking function producing value 
    getasyncdata(i, function(value){ 
     // this is spread over 3 lines to simulate non atomic operation. 
     tmp = accumulator; 
     tmp = tmp + value; 
     accumulator = tmp; 
    }); 
    } 
    console.log(accumulator); 
} 

, как я вижу его GetData обратных вызовов будут называться 100 раз в parrallel ... и есть Hight шансы аккумулятор обыкновения быть суммой 100 значений, так как обратный вызов не атомный (или это?) ...

Как вы думаете?

+3

Узел однопоточный, поэтому ваши операции асинхронного сканирования фактически не выполняются в одно и то же время. – Blender

+1

С другой стороны, 'аккумулятора ', вероятно, будет 0 в то время, когда вы запускаете его консоль, поскольку функция isync – adeneo

+1

Кроме того, если вы используете кластер, то операции могут фактически выполняться в одно и то же время. См. Http://nodejs.org/api/cluster.html – Ryan

ответ

2

Вы можете использовать функцию, которая проверяет, является ли работает какое-либо задание, а затем печатает, если мы сделали. Например:

function test(){ 
    var accumulator = 0, pendingOps = 0; 

    for(int i= 0; i<100; i++){ 
    // non blocking function producing value 
    pendingOps++; 
    getasyncdata(i, function(value){ 
     // this is spread over 3 lines to simulate non atomic operation. 
     tmp = accumulator; 
     tmp = tmp + value; 
     accumulator = tmp; 
     printIfFinished(); 
    }); 

    function printIfFinished() { 
     pendingOps--; 
     if(pendingOps) == 0 { 
     console.log(accumulator); 
     } 
    } 
    } 
} 

Есть много библиотек потоков управления, которые помогут вам сделать это, два из наиболее популярных из них:

+0

Как я могу быть уверен, что код фактически распараллелен, что если getasyncdata callback не вызывается быстрее, чем срабатывает следующий getasyncdata ... это получило бы printIfFinished до того, как pendingOps будет увеличиваться ... нет? Представьте, что getasyncdata не блокируется. – Patrice

+0

Пакет отлично подходит для более сложной ситуации, спасибо за подсказку. Это то, что я искал. – Patrice

-1

Хотя фактические операции асинхронного действия могут происходить одновременно (в отдельных потоках), только один обратный вызов будет запущен в заданное время из-за того, что цикл событий Nodes является одиночным. Таким образом, гарантируется, что accumulator действительно будет суммой всех значений.

Что касается вашего кода примера, то console.log(accumulator) будет равен нулю, поскольку getasyncdata не блокирует, и, таким образом, console.log будет выполняться до завершения асинхронных вызовов. Если вы хотите, чтобы войти в окончательных накопленные данных, вы можете реализовать его следующим образом:

function test() { 
    var accumulator = 0; 
    var counter = 0; 
    for (int i = 0; i < 100; i++) { 
     // non blocking function producing value 
     getasyncdata(i, function (value) { 
      // this is spread over 3 lines to simulate non atomic operation. 
      tmp = accumulator; 
      tmp = tmp + value; 
      accumulator = tmp; 
      counter++; 
      if (counter == 100) { 
       console.log(accumulator); 
      } 
     }); 
    } 
} 
+0

Хотя это верно, в то время, когда он регистрируется, он не будет показывать правильное значение при условии, что getasyncdata действительно является асинхронным (использует setImmediate или process.nextTick) – Ryan

Смежные вопросы