Array.forEach
не обеспечивает эту тонкость (о, если бы это было), но есть несколько способов выполнить то, что вы хотите:
Используя простой счетчик
function callback () { console.log('all done'); }
var itemsProcessed = 0;
[1, 2, 3].forEach((item, index, array) => {
asyncFunction(item, () => {
itemsProcessed++;
if(itemsProcessed === array.length) {
callback();
}
});
});
(спасибо @vanuan и другим). Этот подход гарантирует, что все элементы обрабатываются перед вызовом «готового» обратного вызова. Вам нужно использовать счетчик, который обновляется в обратном вызове. В зависимости от значения параметра index не предоставляется одна и та же гарантия, поскольку порядок возврата асинхронных операций не гарантируется.
Использование обещаний ES6
(библиотека обещаний может использоваться для старых браузеров):
Обработка всех запросов, гарантирующих синхронное выполнение (например, 1, затем 2, затем 3).
function asyncFunction (item, cb) {
setTimeout(() => {
console.log('done with', item);
cb();
}, 100);
}
let requests = [1, 2, 3].reduce((promiseChain, item) => {
return promiseChain.then(() => new Promise((resolve) => {
asyncFunction(item, resolve);
}));
}, Promise.resolve());
requests.then(() => console.log('done'))
Обрабатывать все асинхронные запросы без «синхронного» выполнения (2 могут закончиться быстрее, чем 1)
let requests = [1,2,3].map((item) => {
return new Promise((resolve) => {
asyncFunction(item, resolve);
});
})
Promise.all(requests).then(() => console.log('done'));
Использование асинхронной библиотеки
Есть и другие асинхронные библиотеки, async является наиболее популярным, которые обеспечивают механизмы , чтобы выразить то , что вы хотите.
редактировать
Основная часть вопроса была отредактирована для удаления ранее синхронного примера кода, поэтому я обновил свой ответ, чтобы уточнить. В исходном примере для моделирования асинхронного поведения использовался синхронный код, поэтому применялось следующее:
array.forEach
является синхронным и так же res.write
, так что вы можете просто поставить свой обратный вызов после вызова для foreach:
posts.foreach(function(v, i) {
res.write(v + ". index " + i);
});
res.end();
forEach
метода массива былdone
параметрallDone
обратного вызова и обратный вызов!