Aby na pewno zrozumieć, co się dzieje, musiałem wprowadzić pewne zmiany w skrypcie, ale oto są.
Po pierwsze, możesz wiedzieć, jak node
i jak to event loop
działa, ale pozwól mi szybko podsumować. Po uruchomieniu skryptu node
środowisko wykonawcze najpierw uruchamia jego synchroniczną część, a następnie planuje wykonanie promises
i timers
do wykonania w następnych pętlach, a po zaznaczeniu, że zostały one rozwiązane, uruchom wywołania zwrotne w innej pętli. Ta prosta treść wyjaśnia to bardzo dobrze, podziękowania dla @StephenGrider:
const pendingTimers = [];
const pendingOSTasks = [];
const pendingOperations = [];
// New timers, tasks, operations are recorded from myFile running
myFile.runContents();
function shouldContinue() {
// Check one: Any pending setTimeout, setInterval, setImmediate?
// Check two: Any pending OS tasks? (Like server listening to port)
// Check three: Any pending long running operations? (Like fs module)
return (
pendingTimers.length || pendingOSTasks.length || pendingOperations.length
);
}
// Entire body executes in one 'tick'
while (shouldContinue()) {
// 1) Node looks at pendingTimers and sees if any functions
// are ready to be called. setTimeout, setInterval
// 2) Node looks at pendingOSTasks and pendingOperations
// and calls relevant callbacks
// 3) Pause execution. Continue when...
// - a new pendingOSTask is done
// - a new pendingOperation is done
// - a timer is about to complete
// 4) Look at pendingTimers. Call any setImmediate
// 5) Handle any 'close' events
}
// exit back to terminal
Pamiętaj, że pętla zdarzeń nigdy się nie skończy, dopóki nie zostaną wykonane zadania systemu operacyjnego. Innymi słowy, wykonanie węzła nigdy się nie skończy, dopóki nie zostaną oczekujące żądania HTTP.
W twoim przypadku uruchamia async
funkcję, ponieważ zawsze zwróci obietnicę, zaplanuje wykonanie w następnej iteracji pętli. W funkcji asynchronicznej planujesz kolejne 1000 obietnic (żądań HTTP) jednocześnie w tej map
iteracji. Następnie czekasz na wszystko, a następnie zdecydujesz się zakończyć program. Na pewno zadziała, chyba że twoja anonimowa funkcja strzałki map
nie zgłasza żadnego błędu . Jeśli jeden z twoich obietnic zgłasza błąd i nie poradzić, niektóre z obietnic nie będzie miał ich zwrotna nazywa kiedykolwiek dzięki czemu program do zakończenia , ale nie do wyjścia , bo pętla zdarzenie uniemożliwi jej wyjściu aż rozwiązuje wszystkie zadania, nawet bez oddzwaniania. Jak napisano wPromise.all
dokumenty : odrzuci, gdy tylko pierwsza obietnica odrzuci.
Twój ECONNRESET
błąd nie jest związany z samym węzłem, jest czymś w twojej sieci, która spowodowała, że pobieranie zwróciło błąd, a następnie uniemożliwiło zakończenie pętli zdarzeń. Dzięki tej małej poprawce można zobaczyć, że wszystkie żądania są rozwiązywane asynchronicznie:
const fetch = require("node-fetch");
(async () => {
try {
const promises = Array(1000)
.fill(1)
.map(async (_value, index) => {
try {
const url = "https://google.com/";
const response = await fetch(url);
console.log(index, response.statusText);
return response;
} catch (e) {
console.error(index, e.message);
}
});
await Promise.all(promises);
} catch (e) {
console.error(e);
} finally {
console.log("Done");
}
})();
npx envinfo
działania twojego przykładu na moim skrypcie Win 10 / nodev10.16.0 kończy się na 8432.805ms