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

280
Vistas
¿Cuál es la mejor manera de manejar las interrupciones de funciones en javascript?

Básicamente tengo dos funciones asíncronas. Uno de ellos es un tiempo de espera simple de 5 segundos y el otro es una función asíncrona complicada con varios pasos. Aquí hay un ejemplo

 const delay = ms => new Promise(res => setTimeout(res, ms)); class Runner { async start() { let printStuff = async () => { for(let i = 0 ; i < 50; i++){ console.log(i); await delay(50); } } let printLetters = new Promise(async function(resolve, reject) { const length = Math.floor(Math.random() * 10) //dont know how long this will take for(let i = 0; i < length; i++){ await printStuff(); } resolve('letters'); }); let timeout = new Promise(async function(resolve, reject) { await delay(5000); resolve('timeout') }); const finished = await Promise.all([timeout, printLetters]); if(finished === 'timeout'){ this.stop(); } } stop(){ //stop printing stuff instantly } } const myRunner = new Runner(); myRunner.start(); //could call myRunner.stop(); if the user canceled it

La forma en que implementaría esto agregaría una variable global e incluiría una declaración if dentro del ciclo for para verificar si se ha llamado a la interrupción, pero me pregunto si hay una mejor manera de implementar esto. Un problema con esta solución sería que imprimiría algunos números más. Tendría que agregar otra verificación al otro bucle for y esto podría complicarse rápidamente.

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

0

Aquí hay una demostración simple que usa mi propia biblioteca.

 import { CPromise } from "c-promise2"; const task = CPromise.promisify(function* () { let printStuff = CPromise.promisify(function* () { for (let i = 0; i < 10; i++) { console.log(i); yield CPromise.delay(100); } }); const length = Math.floor(Math.random() * 10) + 3; //dont know how long this will take for (let i = 0; i < length; i++) { yield printStuff(); } return "letters"; }); const promise = task() .timeout(5000) .then( (result) => console.log(`Done: ${result}`), (err) => console.warn(`Fail: ${err}`) ); setTimeout(() => { promise.cancel(); }, 2000);
about 4 years ago · Juan Pablo Isaza Denunciar

0

¿Es esto lo que buscas?

Qué cambió:

  • Promise.all reemplazado por Promise.race
  • se agregó isStopped prop que hace que la "función asíncrona complicada con múltiples pasos" omita la ejecución de los pasos restantes. aunque no lo mata. Las promesas no son cancelables .

 const delay = ms => new Promise(res => setTimeout(res, ms)); class Runner { isStopped = false; async start() { const printStuff = async () => { let i = 0; while (!this.isStopped) { console.log(i++); await delay(50); } } const printLetters = new Promise( resolve => printStuff() .then(() => resolve('letters')) ); const timeout = new Promise( resolve => delay(5000) .then(() => resolve('timeout')) ); const finished = await Promise.race([timeout, printLetters]); console.log({ finished }); if (finished === 'timeout') { this.stop(); } } stop() { this.isStopped = true; } } const myRunner = new Runner(); myRunner.start();
 <button onclick="myRunner.stop()">stop</button>


Respuesta inicial (lo dejó como lo mencionan los comentarios, no lo que está arriba; y en caso de que alguien lo encuentre útil en 2074 ):

Aquí hay un ejemplo que describe lo que estaba sugiriendo en el comentario. run() a continuación devuelve una carrera entre un rechazo que ocurre después de 1s y un cumplidor que se resuelve en un tiempo aleatorio entre 0 y 2s .

 const rejector = (timeout) => new Promise((resolve, reject) => { setTimeout(reject, timeout, 'rejected') }); class Runner { run() { return Promise.race([ rejector(1000), new Promise((resolve, reject) => { setTimeout(resolve, Math.random() * 2000, 'fulfilled') }) ]) } } const t0 = performance.now(); [...Array(6).fill()].forEach((_, key) => { const runner = new Runner(); runner.run() .then(r => console.log(`Proomise ${key} ${r} after ${performance.now() - t0}ms`)) .catch(err => console.log(`Promise ${key} ${err} after ${performance.now() - t0}ms`)); })

Nota: inicialmente coloqué el rechazo dentro de la clase pero (al menos para el ejemplo anterior) no veo por qué no debería permanecer fuera (en un caso real, importado de un archivo auxiliar).

about 4 years ago · Juan Pablo Isaza Denunciar

0

Si necesita una capacidad de parada instantánea, probablemente desee ejecutar el trabajo de impresión como un script externo. Luego usa procesos secundarios como este.

 const { spawn } = require('child_process'); class Runner { ...... start() { this.job[somejobId] = spawn('command to execute script'); //this can be anything, including a node script, eg `node start.js` ..... } stop(jobId) { if (jobId) { //this will kill the script that you spawn above this.job[jobId].kill('SIGHUP'); } } stopAllJobs() { // looping through the job queue to kill all the jobs this.job.forEach(job => job.kill('SIGHUP')) } }

Tendrá más información sobre cómo iniciar un proceso secundario desde el sitio web de node doc https://nodejs.org/api/child_process.html#subprocesskillsignal

Si su trabajo (script externo) se está estancando , se recomienda que solo use los códigos anteriores si tiene un mínimo de 2 núcleos de CPU; de lo contrario, afectará su proceso principal si su script es pesado.

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