Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

166
Views
¿Existe una mejor implementación para este bucle asíncrono en JS?

Así que estoy escribiendo un script node.js que usa Playwright para enviar diferentes mensajes en un intervalo establecido en un navegador. Tengo un problema con una parte asíncrona del script.

Inicialmente lo tenía configurado de esta manera.

 async start() { this.interval = setInterval(async () => { await sendMessages(this.messages); }, 1000); }

Estoy bastante seguro de que la palabra clave await no hace nada aquí y solo ejecuta la siguiente iteración después de 1000 ms, independientemente de si sendMessages terminó de ejecutarse o no. Esto provocaba que los mensajes se enviaran dos veces cuando alcanzaban el requisito de intervalo para volver a enviarse.

Este código funciona, y es el tema de mi pregunta:

 async start() { while (!this.stopFlag) { await sendMessages(this.messages); await timeout(1000); } }

timeout es una función simple que resuelve una Promesa después de una llamada a setTimeout . Sin embargo, esto parece un poco raro y realmente no me gusta esta forma de implementación. ¿Alguien tiene una forma más inteligente de ejecutar algo como esto?

Aquí hay algunos detalles más del código:

Mensajero.js

 import Message from './Message.js' import { timeout } from './Timeout.js' export default class Messenger { constructor(messages, page) { this.page = page; this.messages = messages.map((msg) => new Message(msg)); this.stopFlag = false; } async start() { while (!this.stopFlag) { await this.sendMessages(); await timeout(1000); } } async sendMessages() { for (const message of this.messages) { if (message.shouldSend()) { await message.send(this.page); } } } stop() { this.stopFlag = true; } }

Mensaje.js

 export default class Message { constructor(message) { this.text = message.text; this.timing = message.timing; this.lastSent = null; } async send(page) { logMessage(`Sending message "${this.text}" in channel.`); await playwrightFunctionToSendMessage(); this.lastSent = new Date(); } shouldSend() { // returns a boolean based on this.timing and this.lastSent } }
about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

await dentro setInterval no funcionará como se esperaba y seguirá agregando llamadas a la cola y seguirá adelante.

 this.interval = setInterval(async () => { await sendMessages(this.messages); // will not be async as expected }, 1000);

si existe la posibilidad de que su lógica tarde más en ejecutarse que el intervalo de tiempo, se recomienda que llame recursivamente a una función con nombre usando setTimeout(). Por ejemplo, si usa setInterval() para sondear un servidor remoto cada 5 segundos, la latencia de la red, un servidor que no responde y muchos otros problemas podrían evitar que la solicitud se complete en el tiempo asignado. Como tal, es posible que se encuentre con solicitudes XHR en cola que no necesariamente regresarán en orden.

El desafío es si necesita que los procesos de ejecución prolongada se ejecuten en tiempos establecidos y necesita un resultado antes del próximo tiempo de ejecución. Obviamente, si el proceso lleva más tiempo que el intervalo, necesitará una forma más avanzada de realizar un seguimiento de los lotes o reducir la carga de trabajo.

Pero si simplemente desea una forma de esperar hasta que finalice antes de ejecutar el proceso nuevamente después de un retraso, puede hacerlo:

 function sendMessages() { return new Promise((resolve) => { setTimeout(() => { console.info('done sending'); return resolve(); }, 2000); }) } let stopFlag = false; async function process() { if (stopFlag) { console.info('stopping'); } else { // wait till complete and set a new timeout await sendMessages(); setTimeout(() => process(), 1000); } } process(); // trigger a stop setTimeout(() => { stopFlag = true; }, 5000);

about 4 years ago · Juan Pablo Isaza Report

0

En lugar de que el método de stop reasigne this.stopFlag , borre el intervalo o el tiempo de espera.

 async start() { if (this.timeoutId) return; // timeout is already running - don't start another const startTimeout = () => { this.timeoutId = setTimeout(() => { this.sendMessages() .then(() => { if (this.timeoutId) startTimeout(); }) .catch(handleErrors); // don't forget this part }, 1000); // 1 second between finish of last sendMessages and start of next }; startTimeout(); } stop() { clearTimeout(this.timeoutId); this.timeoutId = null; }
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!