2015-05-14 2 views
2

Я нахожусь в конце запроса POST, который содержит массив объектов (requestArray). Прежде чем я отвечу на POST, мне нужно передать объекты массива через ряд функций последовательно. Я выбрал асинхронную библиотеку, чтобы помочь мне с этой задачей, но мне трудно контролировать поток выполнения кода.async.series вложенные в async.eachSeries цикл завершает раннюю отправку ответа POST

Я использую глобальный массив для хранения результатов каждой функции (responseArray). Некоторые функции зависят от результата предыдущих функций. Я не хочу использовать async.waterfall(), потому что 1. Мне придется переписать мой код и 2. Я могу столкнуться с тем же вопросом завершения цикла. Ниже мой код проблемный код.

app.post('/test', function(req, res) { 
    var importArray = req.body; 
    var iteration = 0; 

    async.eachSeries(importArray, function(data, callback) { 
    var index = importArray.indexOf(data); 
    var element = data.element; 
    exportArray[index] = []; 

    async.series([ 
     function(callback) { 
     process1(data, index, callback); 
     }, 
     function(callback) { 
     process2(element, index, callback); 
     }, 
     function(callback) { 
     process3(element, index, callback); 
     }], 
     function(err, results) { 
     var str = {}; 
     results.forEach(function(result) { 
      if (result) { 
       str += result + ','; 
      } 
     }); 
     //callback();  // callback here = synchronous execution. 
     if (index === req.body.length - 1) { 
      res.send(exportArray); 
     } 
     }); 
     console.log('async.eachSeries() callback iteration # = ' + iteration); 
     iteration++; 
     callback();   // callback here = asynchronous execution. 
    }, function(err){ 
     if(err) { 
     console.log('Error'); 
     } else { 
     console.log('All data has been processes successfully.'); 
     } 
    }); 
}); 

Каждая функция async.series() возвращает обратный вызов (null, result). После того, как process1() вернет обратный вызов, async.eachSeries() перейдет к следующей записи массива раньше, что идеально. Однако async.eachSeries() выполняет ответ POST перед возвратом всех результатов async.series(). Как я могу пересмотреть свой код, чтобы async.eachSeries() завершил выполнение после того, как все результаты importArray (exportArray) возвращаются из process1 - 3, прежде чем отправить ответ POST?

ответ

1

Я предлагаю для удобства следовать асинхронному характеру вашего кода, чтобы немного переименовать ваши обратные вызовы. Также, чтобы дождаться, пока каждая из сери закончит, переместите res.send в eachSeries окончательный обратный вызов, проходящий в results.

Вот обновленный код.

app.post('/test', function(req, res) { 
    var importArray = req.body; 
    var iteration = 0; 

    async.eachSeries(importArray, function(data, next) { 
    var index = importArray.indexOf(data); 
    var element = data.element; 
    exportArray[index] = []; 

    async.series([ 
     function(cb) { 
     process1(data, index, cb); 
     }, 
     function(cb) { 
     process2(element, index, cb); 
     }, 
     function(cb) { 
     process3(element, index, cb); 
     }], 

     function(err, results) { 
     var str = {}; 
     results.forEach(function(result) { 
      if (result) { 
       str += result + ','; 
      } 
     }); 

     console.log('async.eachSeries() callback iteration # = ' + iteration); 
     iteration++; 
     next(null, results);  
     });  

    }, function(err, results){ 
     if(err) { 
     return console.log('Error'); 
     } 

     res.send(exportArray); 
     console.log('All data has been processes successfully.'); 
    }); 
}); 
+0

Спасибо за пересмотр, Bulkan. 'next (null, results)' бросает ошибку, потому что 'results' не находится в области видимости. Кроме того, должен ли я иметь 2 'res.send (exportArray)' утверждения? – coolcat44

+0

Я смог выполнить ваши изменения, и он работает правильно. Однако он работает синхронно. Я копирую свой код, который я должен запускать асинхронно. – coolcat44

1

После помощи @Bulkan и лужения, я получил код асинхронно работать с помощью моего старого друга, «флаг». Вот код:

app.post('/test', function(req, res) { 
    var importArr = req.body; 
    var iteration = 0; 
    var flag  = false; 

    async.eachSeries(importArr, function(data, cb) { 
    var index  = importArr.indexOf(data); 
    var element  = data.element; 
    exportArr[index] = []; 

    async.series([ 
     function(cb) { 
     process1(data, index, cb); 
     }, 
     function(cb) { 
     process2(element, index, cb); 
     }, 
     function(cb) { 
     process3(element, index, cb); 
     }], 

     function(err, results) { 
     var str = {}; 
     results.forEach(function(result) { 
      if (result) { 
       str += result + ','; 
      } 
     }); 
     iteration++; 
     if (iteration === req.body.length) { 
      flag = true; 
      res.send(exportArr); 
     } 
     }); 
     console.log('async.eachSeries() callback iteration # = ' + iteration); 

     if (iteration < req.body.length) { 
     cb(); 
     } else if (flag) { 
     cb(); 
     } 
    }, function(err){ 
     if (err) { 
     console.log('Error'); 
     } else { 
     console.log('All data has been processes successfully.'); 
     } 
    }); 
});