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 nodee como event loopfunciona, mas deixe-me fazer uma rápida recapitulação. Quando você executar um script, nodetempo de execução primeiro executar a parte síncrona de que, em seguida, agendar o promisese timersa 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 asyncfunçã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 mapiteraçã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 ECONNRESETerro 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 envinfoexemplo, executando o seu exemplo no meu script Win 10 / nodev10.16.0, que termina em 8432.805ms