Короткая зарисовка на тему управления потоком выполнения с помощью async. В большом приложении профит от применения этого модуля трудно переоценить. Я использую его уже не первый год и сегодня попробую показать пару приемов. На мой взгляд async - лучшее на текущий момент лекарство от Callback Hell.
Например мы получаем данные...
... после чего с ними необходимо произвести определенные манипуляции...
Код нашего приложения может выглядеть следующим образом:
Результат работы приложения:
Но если мы решим вывести в консоль результат только после завершения обработки всех данных, да еще и обработать ошибки, которые могут возникнуть в процессе наших асинхронных манипуляций, то модуль async будет очень даже кстати:
Усложняем задачу - после получения данных выполняем две асинхронные манипуляции с каждым полученным объектом параллельно:
Для полноты ощущений добавим еще одну манипуляцию, которая будет выполняться только после завершения первых двух:
Но какого коллайдера мы дважды проверяем наличие ошибок если есть возможность получить их в одном месте?
Для правды жизни выкинем ошибку в самой первой функции:
Вот теперь все по фэн-шую. Если вы все еще кипятите, то сейчас самое время начать избавляться от бесконечной лапши коллбэков.
На этом прощаюсь, и да пребудет с вами сила :)
Например мы получаем данные...
function getData(cb) {
setTimeout(function() {
console.log('Getting data...');
return cb([{a: 3}, {a: 5}]);
}, 1000);
}
... после чего с ними необходимо произвести определенные манипуляции...
function add(obj, cb) {
setTimeout(function() {
obj.b = obj.a + obj.a;
console.log('%d plus %d = %d', obj.a, obj.a, obj.b);
cb();
}, 1000);
}
Код нашего приложения может выглядеть следующим образом:
getData(function(data) {
data.forEach(function(obj) {
add(obj, function() {
console.log('obj:', obj);
});
});
});
function getData(cb) {
setTimeout(function() {
console.log('Getting data...');
return cb([{a: 3}, {a: 5}]);
}, 1000);
}
function add(obj, cb) {
setTimeout(function() {
obj.b = obj.a + obj.a;
console.log('%d plus %d = %d', obj.a, obj.a, obj.b);
cb();
}, 1000);
}
Результат работы приложения:
Но если мы решим вывести в консоль результат только после завершения обработки всех данных, да еще и обработать ошибки, которые могут возникнуть в процессе наших асинхронных манипуляций, то модуль async будет очень даже кстати:
var async = require('async');
getData(function(data) {
async.each(data, function(obj, next) {
add(obj, next);
}, function(err) {
if (err) console.log('err:', err);
console.log('data:', data);
});
});
function getData(cb) {
setTimeout(function() {
console.log('Getting data...');
return cb([{a: 3}, {a: 5}]);
}, 1000);
}
function add(obj, cb) {
setTimeout(function() {
obj.b = obj.a + obj.a;
console.log('%d plus %d = %d', obj.a, obj.a, obj.b);
cb();
}, 1000);
}
Усложняем задачу - после получения данных выполняем две асинхронные манипуляции с каждым полученным объектом параллельно:
var async = require('async');
getData(function(data) {
async.each(data, function(obj, next) {
async.parallel([
function(cb){ add(obj, cb); },
function(cb){ multiply(obj, cb); }
], next);
}, function(err) {
if (err) console.log('err:', err);
console.log('data:', data);
});
});
function getData(cb) {
setTimeout(function() {
console.log('Getting data...');
return cb([{a: 3}, {a: 5}]);
}, 1000);
}
function add(obj, cb) {
setTimeout(function() {
obj.b = obj.a + obj.a;
console.log('%d plus %d = %d', obj.a, obj.a, obj.b);
cb();
}, 1000);
}
function multiply(obj, cb) {
setTimeout(function() {
obj.c = obj.a * obj.a;
console.log('%d times %d = %d', obj.a, obj.a, obj.c);
cb();
}, 1000);
}
Для полноты ощущений добавим еще одну манипуляцию, которая будет выполняться только после завершения первых двух:
var async = require('async');
getData(function(data) {
async.each(data, function(obj, next) {
async.parallel([
function(cb){ add(obj, cb); },
function(cb){ multiply(obj, cb); }
], next);
}, function(err) {
if (err) console.log('err:', err);
async.each(data, function(obj, next) {
subtract(obj, next);
}, function(err) {
if (err) console.log('err:', err);
console.log('data:', data);
});
});
});
function getData(cb) {
setTimeout(function() {
console.log('Getting data...');
return cb([{a: 3}, {a: 5}]);
}, 1000);
}
function add(obj, cb) {
setTimeout(function() {
obj.b = obj.a + obj.a;
console.log('%d plus %d = %d', obj.a, obj.a, obj.b);
cb();
}, 1000);
}
function multiply(obj, cb) {
setTimeout(function() {
obj.c = obj.a * obj.a;
console.log('%d times %d = %d', obj.a, obj.a, obj.c);
cb();
}, 1000);
}
function subtract(obj, cb) {
setTimeout(function() {
obj.d = obj.c - obj.b;
console.log('%d minus %d = %d', obj.c, obj.b, obj.d);
cb();
}, 1000);
}
Но какого коллайдера мы дважды проверяем наличие ошибок если есть возможность получить их в одном месте?
Для правды жизни выкинем ошибку в самой первой функции:
var async = require('async');
getData(function(data) {
async.waterfall([
function(callback){
async.each(data, function(obj, next) {
async.parallel([
function(cb){ add(obj, cb); },
function(cb){ multiply(obj, cb); }
], next);
}, callback);
},
function(callback){
async.each(data, function(obj, next) {
subtract(obj, next);
}, callback);
}
], function(err) {
if (err) console.log('err:', err.message);
console.log('data:', data);
});
});
function getData(cb) {
setTimeout(function() {
console.log('Getting data...');
return cb([{a: 3}, {a: 5}]);
}, 1000);
}
function add(obj, cb) {
setTimeout(function() {
if (obj.a === 3) return cb(new Error('Achtung!'));
obj.b = obj.a + obj.a;
console.log('%d plus %d = %d', obj.a, obj.a, obj.b);
cb();
}, 1000);
}
function multiply(obj, cb) {
setTimeout(function() {
obj.c = obj.a * obj.a;
console.log('%d times %d = %d', obj.a, obj.a, obj.c);
cb();
}, 1000);
}
function subtract(obj, cb) {
setTimeout(function() {
obj.d = obj.c - obj.b;
console.log('%d minus %d = %d', obj.c, obj.b, obj.d);
cb();
}, 1000);
}
Вот теперь все по фэн-шую. Если вы все еще кипятите, то сейчас самое время начать избавляться от бесконечной лапши коллбэков.
На этом прощаюсь, и да пребудет с вами сила :)






Комментариев нет:
Отправить комментарий
Комментарий будет опубликован после модерации