Array.forEach
nie zapewnia tej subtelności (och, gdyby tak było), ale istnieje kilka sposobów na osiągnięcie tego, co chcesz:
Za pomocą prostego licznika
function callback () { console.log('all done'); }
var itemsProcessed = 0;
[1, 2, 3].forEach((item, index, array) => {
asyncFunction(item, () => {
itemsProcessed++;
if(itemsProcessed === array.length) {
callback();
}
});
});
(dzięki @vanuan i innym) Takie podejście gwarantuje, że wszystkie elementy zostaną przetworzone przed wywołaniem wywołania zwrotnego „gotowe”. Musisz użyć licznika, który jest aktualizowany w wywołaniu zwrotnym. W zależności od wartości parametru indeksu nie zapewnia tej samej gwarancji, ponieważ kolejność zwrotu operacji asynchronicznych nie jest gwarantowana.
Korzystanie z obietnic ES6
(w starszych przeglądarkach można użyć biblioteki obietnic):
Przetwarzaj wszystkie żądania gwarantujące synchroniczne wykonanie (np. 1, 2, 3, 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'))
Przetwarzaj wszystkie żądania asynchroniczne bez wykonania „synchronicznego” (2 może zakończyć się szybciej niż 1)
let requests = [1,2,3].map((item) => {
return new Promise((resolve) => {
asyncFunction(item, resolve);
});
})
Promise.all(requests).then(() => console.log('done'));
Korzystanie z biblioteki asynchronicznej
Istnieją inne biblioteki asynchroniczne , z których najpopularniejsze to asynchroniczne , które zapewniają mechanizmy wyrażania tego, co chcesz.
Edytować
Treść pytania została poddana edycji w celu usunięcia wcześniej zsynchronizowanego przykładowego kodu, więc zaktualizowałem swoją odpowiedź, aby wyjaśnić. W oryginalnym przykładzie wykorzystano synchroniczny kod podobny do modelowania zachowania asynchronicznego, dlatego zastosowano następujące zasady:
array.forEach
jest zsynchronizowany i tak też jest res.write
, więc możesz po prostu oddzwonić po połączeniu, aby foreach:
posts.foreach(function(v, i) {
res.write(v + ". index " + i);
});
res.end();
forEach
metoda tablicowa miaładone
parametrallDone
wywołania zwrotnego i wywołanie zwrotne!