У меня есть служебная функция after
.
var after = function _after(count, f) {
var c = 0, results = [];
return function _callback() {
switch (arguments.length) {
case 0: results.push(null); break;
case 1: results.push(arguments[0]); break;
default: results.push(Array.prototype.slice.call(arguments)); break;
}
if (++c === count) {
f.apply(this, results);
}
};
};
Следующий код ниже будет работать.Поскольку javascript является однопоточным.
function doWork(work) {
work(10);
work(20);
work(30);
}
WorkHandler(doWork);
function WorkHandler(cb) {
var counter = 0,
finish;
cb(function _work(item) {
counter++;
// somethingAsync calls `finish` when it's finished
somethingAsync(item, function _cb() {
finish()
});
});
finish = after(counter, function() {
console.log('work finished');
});
};
Наверное, я должен объяснить.
Мы передаем функцию, которая работает, обработчику.
Рабочий обработчик вызывает его ипереходит в работу.
Функция, которая выполняет рабочие вызовы, работает многократно увеличивая счетчик
Поскольку функция, которая работает, не является асинхронной (очень важной), мы можем определить функцию финиша после того, как онаготово.
Асинхронная работа, которая выполняется, не может завершиться (и вызвать неопределенную функцию завершения) до завершения текущего синхронного блока работы (выполнения всего обработчика).
Это означает, чточто после того, как весь обработчик завершит работу (и будет задана переменная finish), асинхронные рабочие задания начнут заканчиваться и вызовут окончания.Только после того, как все они вызовут финиш, обратный вызов отправит на after
fire.