Para entender lo que estaba sucediendo con seguridad, necesitaba hacer algunas modificaciones a su script, pero aquí están.
Primero, puede que sepa cómo node
y cómo event loop
funciona, pero permítame hacer un resumen rápido. Cuando ejecuta un script, el node
tiempo de ejecución primero ejecuta la parte sincrónica del mismo, luego programa el promises
y timers
para que se ejecute en los siguientes bucles, y cuando se verifica que están resueltos, ejecute las devoluciones de llamada en otro bucle. Esta simple explicación lo explica muy bien, crédito a @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
Tenga en cuenta que el bucle de eventos nunca terminará hasta que haya tareas pendientes del sistema operativo. En otras palabras, la ejecución de su nodo nunca terminará hasta que haya solicitudes HTTP pendientes.
En su caso, ejecuta una async
función, ya que siempre devolverá una promesa, programará su ejecución en la siguiente iteración del bucle. En su función asíncrona, programa otras 1000 promesas (solicitudes HTTP) a la vez en esa map
iteración. Después de eso, está esperando que todo se resuelva para finalizar el programa. Funcionará, seguro, a menos que su función de flecha anónima map
no arroje ningún error . Si una de sus promesas arroja un error y no lo maneja, algunas de las promesas no recibirán su devolución de llamada para que el programa finalice pero no para salir , porque el bucle de eventos evitará que salga hasta que se resuelva todas las tareas, incluso sin devolución de llamada. Como dice en elPromise.all
docs : se rechazará tan pronto como se rechace la primera promesa.
Por lo tanto, su ECONNRESET
error no está relacionado con el nodo en sí, es algo con su red que hizo que la búsqueda arroje un error y luego evite que el bucle de eventos finalice. Con esta pequeña solución, podrá ver que todas las solicitudes se resuelven de forma asíncrona:
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
ejecución de su ejemplo en mi script Win 10 / nodev10.16.0 que termina en 8432.805ms