Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

486
Vistas
¿Por qué setInterval nunca se ejecuta, en mi código NodeJs que transmite un generador a un archivo?

Tengo esta situación en mi código NodeJs, que calcula las permutaciones (código de aquí ), pero no importa qué, no obtengo ningún resultado de setInterval .

 const { Readable } = require('stream'); const { intervalToDuration, formatDuration, format } = require('date-fns'); const { subsetPerm } = require('./permutation'); function formatLogs(counter, permStart) { const newLocal = new Date(); const streamTime = formatDuration(intervalToDuration({ end: newLocal.getTime(), start: permStart.getTime() })); const formattedLogs = `wrote ${counter.toLocaleString()} patterns, after ${streamTime}`; return formattedLogs; } const ONE_MINUTES_IN_MS = 1 * 60 * 1000; let progress = 0; let timerCallCount = 1; let start = new Date(); const interval = setInterval(() => { console.log(formatLogs(progress, start)); }, ONE_MINUTES_IN_MS); const iterStream = Readable.from(subsetPerm(Object.keys(Array.from({ length: 200 })), 5)); console.log(`Stream started on: ${format(start, 'PPPPpppp')}`) iterStream.on('data', () => { progress++; if (new Date().getTime() - start.getTime() >= (ONE_MINUTES_IN_MS * timerCallCount)) { console.log(`manual timer: ${formatLogs(progress, start)}`) timerCallCount++; if (timerCallCount >= 3) iterStream.destroy(); } }); iterStream.on('error', err => { console.log(err); clearInterval(interval); }); iterStream.on('close', () => { console.log(`closed: ${formatLogs(progress, start)}`); clearInterval(interval); }) console.log('done!');

Pero lo que encuentro es que imprime '¡hecho!' (esperado) y luego el script parece terminar, aunque si pongo un console.log en mi devolución de llamada on('data') obtengo datos impresos en la terminal. Pero incluso horas más tarde, console.log en setInterval nunca se ejecuta, ya que nada termina en el archivo, además de la salida de on('close',...) .

El registro de salida se parece a:

 > node demo.js Stream started on: Sunday, January 30th, 2022 at 5:40:50 PM GMT+00:00 done! manual timer: wrote 24,722,912 patterns, after 1 minute manual timer: wrote 49,503,623 patterns, after 2 minutes closed: wrote 49,503,624 patterns, after 2 minutes

Los temporizadores en la guía de nodos tienen una sección llamada ' dejando atrás los tiempos de espera ' que parecía relevante. Pero cuando pensé en usar interval.ref(); le dijo a la secuencia de comandos que no recolecte basura el objeto hasta que se llame a .unref() en el mismo objeto de tiempo de espera, en la segunda lectura eso no es del todo correcto y no hace la diferencia.

Estoy ejecutando esto usando npm como npm run noodle que solo apunta al archivo.

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

El generador es síncrono y bloquea el bucle de eventos.

Readable.from procesa todo el generador de una sola vez, por lo que si el generador es sincrónico y de ejecución prolongada, bloquea el bucle de eventos.

Aquí está el código anotado que ejecuta:

 async function next() { for (;;) { try { const { value, done } = isAsync ? await iterator.next() : // our generator is not asynchronous iterator.next(); if (done) { readable.push(null); // generator not done } else { const res = (value && typeof value.then === 'function') ? await value : value; // not a thenable if (res === null) { reading = false; throw new ERR_STREAM_NULL_VALUES(); } else if (readable.push(res)) { // readable.push returns false if it's been paused, or some other irrelevant cases. continue; // we continue to the next item in the iterator } else { reading = false; } } } catch (err) { readable.destroy(err); } break; } }

Aquí está la API para readable.push , que explica cómo esto mantiene el generador en funcionamiento:

Devuelve: verdadero si se pueden seguir enviando fragmentos de datos adicionales; falso en caso contrario.

Nada le ha dicho a NodeJs que no continúe enviando datos, por lo que continúa.

Entre cada ejecución del ciclo de eventos, Node.js verifica si está esperando alguna E/S asíncrona o temporizadores y se apaga limpiamente si no hay ninguno.

Planteé esto como un problema de Github de NodeJs y terminé trabajando en esta solución:

 cosnt yieldEvery = 1e5; function setImmediatePromise() { return new Promise(resolve => setImmediate(resolve)); } const iterStream = Readable.from(async function* () { let i = 0 for await (const item of baseGenerator) { yield item; i++; if (i % yieldEvery === 0) await setImmediatePromise(); } }());

Esto está parcialmente inspirado en este blog de snyk.io , que entra en más detalles sobre este tema.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda