Um zu verstehen, was sicher geschah, musste ich einige Änderungen an Ihrem Skript vornehmen, aber hier sind einige.
Zunächst wissen Sie vielleicht, wie node
und wie es event loop
funktioniert, aber lassen Sie mich kurz zusammenfassen. Wenn Sie ein Skript ausführen, führen Sie zur node
Laufzeit zuerst den synchronen Teil davon aus und planen Sie dann die promises
und timers
, die in den nächsten Schleifen ausgeführt werden sollen. Wenn diese aktiviert sind, führen Sie die Rückrufe in einer anderen Schleife aus. Dieser einfache Kern erklärt es sehr gut, danke an @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
Beachten Sie, dass die Ereignisschleife niemals endet, bis anstehende Betriebssystemaufgaben vorliegen. Mit anderen Worten, Ihre Knotenausführung wird niemals beendet, bis ausstehende HTTP-Anforderungen vorliegen.
In Ihrem Fall wird eine async
Funktion ausgeführt, da immer ein Versprechen zurückgegeben wird und die Ausführung in der nächsten Schleifeniteration geplant wird. In Ihrer asynchronen Funktion planen Sie weitere 1000 Versprechen (HTTP-Anforderungen) gleichzeitig in dieser map
Iteration. Danach warten Sie darauf, dass alle aufgelöst werden, um das Programm zu beenden. Es wird sicher funktionieren, es sei denn, Ihre anonyme Pfeilfunktion auf dem map
löst keinen Fehler aus . Wenn einer Ihrer verspricht einen Fehler wirft und Sie nicht damit umgehen, wird ein Teil der Versprechungen nicht ihre Rückruf jemals das Programm machen namens müssen am Ende aber nicht zu Ausfahrt , weil die Ereignisschleife es zu verlassen , bis es Entschlüssen verhindern alle Aufgaben, auch ohne Rückruf. Wie es auf dem stehtPromise.all
docs : Es wird abgelehnt, sobald das erste Versprechen abgelehnt wird.
Ihr On- ECONNRESET
Fehler hängt also nicht mit dem Knoten selbst zusammen, sondern mit Ihrem Netzwerk, das den Abruf veranlasst hat, einen Fehler auszulösen und dann zu verhindern, dass die Ereignisschleife endet. Mit diesem kleinen Fix können Sie sehen, dass alle Anforderungen asynchron aufgelöst werden:
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
Beispiels veröffentlichen, das auf meinem Win 10 / nodev10.16.0-Skript ausgeführt wird und am