Para entender o que estava acontecendo com certeza, eu precisava fazer algumas modificações no seu script, mas aqui estão elas.
Primeiro, você pode saber como node
e como event loop
funciona, mas deixe-me fazer uma rápida recapitulação. Quando você executar um script, node
tempo de execução primeiro executar a parte síncrona de que, em seguida, agendar o promises
e timers
a ser executado nos próximos loops, e quando verificado que eles são resolvidos, execute os retornos de chamada em outro loop. Esta essência simples explica muito bem, crédito para @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
Observe que o loop de eventos nunca terminará até que haja tarefas pendentes do SO. Em outras palavras, a execução do nó nunca terminará até que haja solicitações HTTP pendentes.
No seu caso, ele executa uma async
função, pois sempre retornará uma promessa, agendará para que seja executada na próxima iteração do loop. Na sua função assíncrona, você agenda outras 1000 promessas (solicitações HTTP) de uma só vez nessa map
iteração. Depois disso, você está aguardando que seja resolvido para concluir o programa. Funcionará, com certeza, a menos que sua seta anônima funcione no erromap
não aconteça . Se uma das suas promessas gerar um erro e você não lidar com elas, algumas delas não terão seu retorno de chamada chamado, fazendo com que o programa termine, mas não saia , porque o loop de eventos impedirá que ele saia até que seja resolvido todas as tarefas, mesmo sem retorno de chamada. Como diz noPromise.all
docs : rejeitará assim que a primeira promessa rejeitar.
Portanto, seu ECONNRESET
erro on não está relacionado ao nó em si, é algo com a sua rede que fez a busca para lançar um erro e impedir que o loop de eventos termine. Com essa pequena correção, você poderá ver todos os pedidos sendo resolvidos de forma assí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
exemplo, executando o seu exemplo no meu script Win 10 / nodev10.16.0, que termina em 8432.805ms