Есть массив, для каждого элемента которого следует вызвать асинхронную функцию, возвращающую значение через коллбэк.
Однако, требуется вызвать их последовательно, а именно, следующий вызов надо совершать только тогда, когда завершилась обработка предыдущего.
Вот так получается одновременно:
function doSmth(x, callback) {
setTimeout(callback, Math.random() * 100 | 0, null, x);
}
var data = [1, 2, 3, 4, 5, 6, 7, 8];
for (var x of data) {
doSmth(x, function (err, res) {
console.log(err || res);
});
}
.as-console-wrapper.as-console-wrapper { max-height: 100vh }
Ответ
Надо делать вызов внутри коллбека. Для этого придётся переписать цикл на рекурсию (ну или не совсем рекурсию):
function doSmth(x, callback) {
setTimeout(callback, Math.random() * 100 | 0, null, x);
}
var data = [1, 2, 3, 4, 5, 6, 7, 8];
(function go(i) { // <================== рекурсивная функция вместо цикла
if (i >= data.length) {
return; // <======================== выход, когда массив закончился
}
doSmth(data[i], function (err, res) {
console.log(err || res);
go(i + 1); // <===================== рекурсивный вызов из коллбэка
});
})(0);
.as-console-wrapper.as-console-wrapper { max-height: 100vh }
И остаётся ещё один момент - обычно нам бы надо узнать, когда завершилась обработка. Для этого функция go вместо return может вызвать другой коллбэк из вызывающей функции:
function doSmth(x, callback) {
setTimeout(callback, Math.random() * 100 | 0, null, x);
}
function process(data, callback) {
(function go(i) { // <================== рекурсивная функция вместо цикла
if (i >= data.length) {
return callback(null, null); // <=== return позволяет избежать рекурсивного вызова
}
doSmth(data[i], function (err, res) {
if (err) {
return callback(err, null); // <== прекращаем дальнейшую обработку
}
console.log(res);
go(i + 1); // <===================== рекурсивный вызов из коллбэка
});
})(0);
}
var data = [1, 2, 3, 4, 5, 6, 7, 8];
process(data, function (err, res) {
console.log(err || "Готово!");
});
.as-console-wrapper.as-console-wrapper { max-height: 100vh }
Комментариев нет:
Отправить комментарий