Что такое простая реализация async.водопад?
Я использую некоторые функции из асинхронный библиотека, и хочу убедиться, что я понимаю, как они делают вещи внутри; однако я застрял на async.waterfall
(реализация здесь). Фактическая реализация использует другие функции из библиотеки, и без большого опыта мне трудно следовать.
может кто-то, не заботясь об оптимизации, предоставить очень просто реализация это обеспечивает функциональность водопада? Вероятно, что-то сравнимое с ответ.
С документы, описание водопада:
запускает массив задач функций последовательно, каждая из которых результаты в массив. Однако, если какая-либо из задач проходит ошибка собственного обратного вызова, следующая функция не выполняется, и основной обратный вызов немедленно вызывается с помощью ошибка.
пример:
async.waterfall([
function(callback) {
callback(null, 'one', 'two');
},
function(arg1, arg2, callback) {
// arg1 now equals 'one' and arg2 now equals 'two'
callback(null, 'three');
},
function(arg1, callback) {
// arg1 now equals 'three'
callback(null, 'done');
}
], function (err, result) {
// result now equals 'done'
});
2 ответов
Ну, вот простая реализация для цепных функций, выстраивая их в очередь.
прежде всего, функция:
function waterfall(arr, cb){} // takes an array and a callback on completion
теперь нам нужно отслеживать массив и перебирать его:
function waterfall(arr, cb){
var fns = arr.slice(); // make a copy
}
давайте начнем с обработки переданного и пустого массива, добавив дополнительный параметр, чтобы мы могли передавать результаты под названием result
:
function waterfall(arr, cb, result){ // result is the initial result
var fns = arr.slice(); // make a copy
if(fns.length === 0){
process.nextTick(function(){ // don't cause race conditions
cb(null, result); // we're done, nothing more to do
});
}
}
что хорошо:
waterfall([], function(err, data){
console.log("Done!");
});
теперь давайте справимся с тем, что у нас есть в:
function waterfall(arr, cb, result){ // result is the initial result
var fns = arr.slice(1); // make a copy, apart from the first element
if(!arr[0]){ // if there is nothing in the first position
process.nextTick(function(){ // don't cause race conditions
cb(null, result); // we're done, nothing more to do
});
return;
}
var first = arr[0]; // get the first function
first(function(err, data){ // invoke it
// when it is done
if(err) return cb(err); // early error, terminate entire call
// perform the same call, but without the first function
// and with its result as the result
waterfall(fns, cb, data);
});
}
и это все! Мы преодолеваем тот факт, что мы не можем цикл с обратными вызовами, используя рекурсию в основном. вот скрипка иллюстрируя его.
стоит отметить, что если бы мы реализовывали его с обещаниями, мы могли бы использовать цикл for.
для тех, кто любит держать его коротким:
function waterfall(fn, done){
fn.length ? fn.shift()(function(err){ err ? done(err) : waterfall(fn, done) }) : done();
}