Javascript: выполнить кучу асинхронного метода с одним обратным вызовом
Мне нужно выполнить кучу асинхронных методов (база данных SQLite клиента) и вызвать только один последний обратный вызов.
Конечно, уродливый способ:
execAll : function(callBack) {
asynch1(function() {
asynch2(function() {
...
asynchN(function() {
callBack();
})
})
});
}
Но я знаю, что есть лучшие способы сделать это. Интуитивно я обнаружил бы, когда вызов был вызван с помощью счетчика для вызова окончательного обратного вызова.
Я думаю, что это обычный дизайн-шаблон, поэтому, если кто-то может указать мне в правильном направлении...
Спасибо заранее!
Ответы
Ответ 1
это легко
var callback = (function(){
var finishedCalls = 0;
return function(){
if (++finishedCalls == 4){
//execute your action here
}
};
})();
Просто передайте этот обратный вызов всем вашим методам, и как только он будет вызван 4 раза, он будет выполнен.
Если вы хотите использовать factory для этого, вы можете сделать следующее
function createCallback(limit, fn){
var finishedCalls = 0;
return function(){
if (++finishedCalls == limit){
fn();
}
};
}
var callback = createCallback(4, function(){
alert("woot!");
});
async1(callback);
async2(callback);
async3(callback);
async4(callback);
Ответ 2
Я написал некоторые утилиты async, которые могут вам пригодиться, что позволяет вам написать ваш пример:
function(callback) {
async.series([
asynch1(),
asynch2(),
...
asynchN()
], callback);
}
Или, если вы хотите запустить их параллельно, как:
function(callback) {
async.parallel([
asynch1(),
asynch2(),
...
asynchN()
], callback);
}
Существует множество других полезных функций, таких как async map/reduce:
http://caolanmcmahon.com/async.html
Надеюсь, что это поможет!
Ответ 3
Вам следует рассмотреть возможность использования шаблона "Отложенные" для асинхронных методов. Вы можете получить дополнительную информацию из этого вопроса и ответов StackOverflow:
Каковы различия между отложенными, обещаниями и будущими в JavaScript?
Отмеченный ответ от jnewman был хорошим на самом деле!
Надеюсь, что это поможет.
Ответ 4
Promises может помочь в этом. Существует два общих сценария - параллельный и последовательный. Параллель может быть выполнена с использованием Promise.all(), последовательный более сложный - задача B может запускаться только тогда, когда выполняется задача A. Здесь образец bare-bones:
// returns a promise that resolves as the task is done
const wrap = (fn, delay) => new Promise(resolve => setTimeout(_ => resolve(fn()), delay));
const task = (fn, delay) => delay ? wrap(fn, delay) : Promise.resolve(fn());
// given a list of promises, execute them one by one.
const sequence = async l => l.reduce(async (a, b) => [].concat(await a, await b));
const tasks = [
task(_ => console.log("hello world")),
task(_ => console.log("hello future"), 1000)
];
sequence(tasks).then(_ => console.log("all done"));
Для выполнения этой работы в браузерах или более старых версиях node вам может понадобиться перевод ES6/7.