Я часто сталкиваюсь с ситуацией, когда задаче async.series требуются результаты нескольких предыдущих задач. async.waterfall недостаточно, поскольку он предоставляет только результат последней предыдущей задачи. async, auto слишком подробен и предоставляет дополнительное ненужное объявление зависимостей.
Пригодится новая функция (или улучшение async.series). Каждая задача получит объект результата, содержащий результаты всех предыдущих задач.
Возможные названия: накапливать, ряды, накапливать
Пример:
async.accumulate({
one: function(callback){
setTimeout(function(){
callback(null, 1);
}, 200);
},
two: function(callback, results){
// results: {one: 1}
setTimeout(function(){
callback(null, 2);
}, 100);
},
three: function(callback, results){
// results: {one: 1, two: 2}
setTimeout(function(){
callback(null, results.one + results.two);
}, 100);
}
},
function(err, results) {
// results is now equal to: {one: 1, two: 2, three: 3}
});
Вы проверяли async.auto
? Он делает нечто очень похожее на то, что вы описываете.
Как я уже упоминал, в сценарии простой серии async.auto слишком подробен. Пользователь должен объявить, что каждый шаг зависит от предыдущего, что приводит к этим уродливым массивам и дублированию имен шагов.
async.auto({
one: function(callback){
setTimeout(function(){
callback(null, 1);
}, 200);
},
two: ["one", function(callback, results){
setTimeout(function(){
callback(null, 2);
}, 100);
}],
three: ["two", function(callback, results){
setTimeout(function(){
callback(null, results.one + results.two);
}, 100);
}
]
},
function(err, results) {
// results is now equal to: {one: 1, two: 2, three: 3}
});
Мы собираемся внести некоторые улучшения в auto в следующем основном выпуске - всегда иметь обратный вызов последним, а также добавить autoInject
(# 608), который определяет зависимости по именам параметров.
Мне не нравится это предложение, потому что оно зависит от порядка ключей объекта - что не гарантируется в средах JS (и гарантируется только в Node для небольших объектов). С массивами это возможно, но это слишком похоже на async.waterfall
. Я не уверен, что нам нужно что-то среднее между auto
и waterfall
, особенно если мы добавляем autoInject
.
Способ добиться того, чего вы хотите:
function seriesAccumulate(tasks, done) {
async.reduce(tasks, [], function (results, task, next) {
task(results, function (err, result) {
results.push(result);
next(err, result);
});
}, done);
}
Я бы не рекомендовал использовать объект для последовательной итерации.
Закрытие этого. Я не думаю, что нам нужен другой метод между series
и waterfall
в стиле.