Поправьте меня, если я ошибаюсь, но от того, что я понял из вашего вопроса я верю, что вы хотите чтобы взять массив, последовательно вызвать функцию асинхронно на каждом члене этого массива, а затем выполнить функцию обратного вызова, когда каждый элемент массива обработан.
Теперь, чтобы выполнить функцию асинхронно в среде браузера мы будем делать что-то вроде this:
Function.prototype.async = function() {
setTimeout.bind(window, this, 0).apply(window, arguments);
};
alert.async(5);
alert(6);
В приведенном выше примере функция setTimeout
используется для вызова данной функции асинхронно, благодаря которой мы впервые видим значение 6
, а затем предупреждение 5
.
Далее, чтобы сделать вашу foreach
функцию асинхронно мы будем делать что-то, как follows:
function forEach(array, funct, callback) {
if (array.length)
funct.async(array[0], forEach.bind(null, array.slice(1), funct, callback));
else callback.async();
}
выше решение не использовать recusrion. Уверен, что функция forEach
ссылается внутри себя, но она вызывается только в функции funct
, которая называется асинхронно. Следовательно, функция forEach
возвращается до того, как она снова вызвана в функции funct
.
Я включил ссылки на JS fiddles перед каждым фрагментом кода. Если у вас есть еще какие-то сомнения, я был бы рад ответить на них.
Edit:
Если вам не нравится, изменяющие prototype
из Function
(@ kitgui.com), то вы можете использовать этот modified code:
var async = Function.prototype.call.bind(function() {
setTimeout.bind(null, this, 0).apply(null, arguments);
});
async(alert, 5);
alert(6);
Поскольку я не ссылается window
в над кодом он также будет работать в не-браузерных средах.
Тогда мы можем переписать функцию forEach
следующим образом:
function forEach(array, funct, callback) {
if (array.length)
async(funct, array[0], forEach.bind(null, array.slice(1), funct, callback));
else async(callback);
}
Там у нас есть это. Не нужно изменять prototype
от Function
. Тело функции async
в значительной степени то же самое. Мы просто создали unbound wrapper для этого, используя call.bind
. Вы можете увидеть live demo для себя.
Бонус:
Вы можете создать errbacks используя вышеупомянутую картину следующим образом (см live demo):
function forEach(array, funct, callback, error) {
if (array.length && !error)
async(funct, array[0], forEach.bind(null, array.slice(1), funct, callback));
else async(callback, error || null);
}
Это эквивалентно forEachSeries
функции в async библиотеке caolan в возрасте до 10 строк кода.
ли первая функция (второй параметр для 'foreach') должна работать на каждом элементе массива асинхронно? –
В этом коде нет ничего асинхронного. Что вы пытаетесь передать? –
Theres что-то асинхронное о названии вопроса ... –