Как следует из названия. Как мне это сделать?
Я хочу позвонить whenAllDone()
после того, как цикл forEach прошел через каждый элемент и выполнил некоторую асинхронную обработку.
[1, 2, 3].forEach(
function(item, index, array, done) {
asyncFunction(item, function itemDone() {
console.log(item + " done");
done();
});
}, function allDone() {
console.log("All done");
whenAllDone();
}
);
Можно ли заставить его работать так? Когда вторым аргументом forEach является функция обратного вызова, которая запускается после прохождения всех итераций?
Ожидаемый результат:
3 done
1 done
2 done
All done!
javascript
node.js
asynchronous
callback
Дэн Андреассон
источник
источник
forEach
метода массива былdone
параметрallDone
обратного вызова и обратный вызов!Ответы:
Array.forEach
не обеспечивает эту тонкость (о, если бы это было), но есть несколько способов выполнить то, что вы хотите:Используя простой счетчик
(спасибо @vanuan и другим). Этот подход гарантирует, что все элементы обрабатываются перед вызовом «готового» обратного вызова. Вам нужно использовать счетчик, который обновляется в обратном вызове. В зависимости от значения параметра index не предоставляется одна и та же гарантия, поскольку порядок возврата асинхронных операций не гарантируется.
Использование обещаний ES6
(библиотека обещаний может использоваться для старых браузеров):
Обработка всех запросов, гарантирующих синхронное выполнение (например, 1, затем 2, затем 3).
Обрабатывать все асинхронные запросы без «синхронного» выполнения (2 могут закончиться быстрее, чем 1)
Использование асинхронной библиотеки
Есть и другие асинхронные библиотеки, async является наиболее популярным, которые обеспечивают механизмы , чтобы выразить то , что вы хотите.
редактироватьОсновная часть вопроса была отредактирована для удаления ранее синхронного примера кода, поэтому я обновил свой ответ, чтобы уточнить. В исходном примере для моделирования асинхронного поведения использовался синхронный код, поэтому применялось следующее:
array.forEach
является синхронным и так жеres.write
, так что вы можете просто поставить свой обратный вызов после вызова для foreach:источник
if(index === array.length - 1)
убратьitemsProcessed
Если вы сталкиваетесь с асинхронными функциями и хотите убедиться, что перед выполнением кода он завершает свою задачу, мы всегда можем использовать возможность обратного вызова.
Например:
Примечание:
functionAfterForEach
это функция, которая должна быть выполнена после выполнения задач foreach.asynchronous
это асинхронная функция, выполняемая внутри foreach.источник
Надеюсь, что это решит вашу проблему, я обычно работаю с этим, когда мне нужно выполнить forEach с асинхронными задачами внутри.
с участием
источник
Странно, сколько неправильных ответов было дано в асинхронном случае! Можно просто показать, что проверка индекса не обеспечивает ожидаемого поведения:
вывод:
Если мы проверим
index === array.length - 1
, обратный вызов будет вызван после завершения первой итерации, в то время как первый элемент еще не завершен!Я думаю, что для решения этой проблемы без использования внешних библиотек, таких как async, лучше всего сохранять длину списка и уменьшать его после каждой итерации. Поскольку есть только одна нить, мы уверены, что нет шансов на состояние гонки.
источник
С ES2018 вы можете использовать асинхронные итераторы:
источник
Мое решение без Promise (это гарантирует, что каждое действие заканчивается до начала следующего):
источник
источник
Это решение для Node.js, которое является асинхронным.
используя пакет async npm.
(JavaScript) Синхронизация цикла forEach с обратными вызовами внутри
источник
Мое решение:
Пример:
источник
Я пробую Easy Way, чтобы решить эту проблему, поделюсь с вами:
request
является функцией библиотеки mssql в узле js Это может заменить каждую функцию или код, который вы хотите. Удачиисточник
источник
Вам не нужен обратный вызов для перебора списка. Просто добавьте
end()
вызов после цикла.источник
res.write
НЕ является асинхронной операцией, поэтому ваш код не будет работать.Простое решение будет как следовать
источник
Как насчет setInterval, чтобы проверить полный счетчик итераций, дает гарантию. не уверен, что он не будет перегружать прицел, но я его использую и, похоже,
источник