Estoy escribiendo un script de nodo para extraer códigos de estado de URL con el módulo https . El script tiene una matriz de URL. Estoy usando un ciclo forEach para iterar sobre ellos y hacer las llamadas https.get().
El problema que veo es que las llamadas https no parecen suceder (o, al menos, no activan su función de devolución de llamada) hasta que se completa todo el bucle forEach, punto en el que parecen ejecutarse.
Aquí está el código con el que estoy trabajando:
const https = require('https') const urls = [ 'https://www.example.com/', 'https://www.example.org/', 'https://www.example.net/', 'https://www.example.com/', 'https://www.example.org/', 'https://www.example.net/', 'https://www.example.com/', 'https://www.example.com/', 'https://www.example.com/', 'https://www.example.com/', 'https://www.example.org/', 'https://www.example.net/', ] function processResponse(response) { console.log(`${Date.now()} - response.statusCode`) } urls.forEach((url) => { console.log(`Getting: ${Date.now()} - ${url}`) https.get(url, (response) => { processResponse(response) }) })La salida es consistentemente algo como:
Getting: 1637980537771 - https://www.example.com/ Getting: 1637980537810 - https://www.example.org/ Getting: 1637980537811 - https://www.example.net/ Getting: 1637980537813 - https://www.example.com/ Getting: 1637980537816 - https://www.example.org/ Getting: 1637980537818 - https://www.example.net/ Getting: 1637980537820 - https://www.example.com/ Getting: 1637980537821 - https://www.example.com/ Getting: 1637980537823 - https://www.example.com/ Getting: 1637980537827 - https://www.example.com/ Getting: 1637980537830 - https://www.example.org/ Getting: 1637980537832 - https://www.example.net/ 1637980537989 - 200 1637980537992 - 200 1637980537995 - 200 1637980537997 - 200 1637980538005 - 200 1637980538006 - 200 1637980538022 - 200 1637980538023 - 200 1637980538024 - 200 1637980538026 - 200 1637980538032 - 200 1637980538035 - 200La marca de tiempo de los códigos de estado siempre está después del último elemento del bucle forEach. Eso es lo que no entiendo.
Con varios miles de direcciones URL y la probabilidad de que se rompan, quiero asegurarme de que cada una se procese individualmente para no perder el progreso si las cosas salen mal.
Estoy abierto a usar otros módulos/enfoques, pero también me gustaría saber qué está pasando aquí, ya que no concuerda con mi modelo mental.
Su https.get() es una función sin bloqueo. No espera a que se complete. Simplemente inicia la operación e inmediatamente regresa. Entonces, su .forEach() simplemente termina iniciando todas las operaciones y luego, un tiempo después, cada una termina y llama a su devolución de llamada.
Si desea un bucle en el que el bucle espera cada operación asíncrona, debe usar un bucle for regular y usar una operación asíncrona que devuelva una promesa. Luego, puede usar await en la operación asincrónica de devolución de promesa y pausará el bucle.
Por ejemplo, podría hacer esto usando async/await y una biblioteca http que devuelve promesas:
const got = require('got'); const urls = [ 'https://www.example.com/', 'https://www.example.org/', 'https://www.example.net/', 'https://www.example.com/', 'https://www.example.org/', 'https://www.example.net/', 'https://www.example.com/', 'https://www.example.com/', 'https://www.example.com/', 'https://www.example.com/', 'https://www.example.org/', 'https://www.example.net/', ] async function runAll() { for (let url of urls) { console.log(`Getting: ${Date.now()} - ${url}`) try { let result = await got(url); console.log(`${Date.now()} - ${result.statusCode}`) } catch(e) { console.log(`${Date.now()} - ${e.message} - ${e.response.statusCode}`); } } } runAll().then(() => { console.log("all done"); }).catch(err => { console.log(err); });Estoy abierto a usar otros módulos/enfoques, pero también me gustaría saber qué está pasando aquí, ya que no concuerda con mi modelo mental.
https.get() no bloquea. Comienza la operación y luego regresa inmediatamente. Esto permite que su ciclo continúe sin esperar a que se complete. Así es como normalmente funcionan las operaciones asincrónicas sin bloqueo en Javascript.