Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

196
Visualizações
Salir del bucle for(ever) mediante una promesa resuelta

Espero que esta sea una pregunta simple, pero actualmente no puedo entenderlo.

Lo que quiero hacer es salir de un ciclo while que contiene un retraso cuando se resuelve una promesa.

En pseudocódigo esto se vería así:

 while( ! promise.resolved ){ doSomthing() await sleep( 5min ) }

El ciclo debe interrumpirse instantáneamente después de que se resuelva la promesa y no esperar a que finalice la sleep .

sleep se implementa actualmente de manera trivial mediante setTimeout , pero se puede implementar de manera diferente.

Me gustaría tener algún tipo de separación espacial entre la promesa esperada y el sueño para mostrar su funcionamiento más claramente*) (y porque espero una solución elegante de la que aprender). Entonces, lo que funcionaría pero no me gusta es algo como:

 while( true ){ doSomething() try { await Promise.race([promise,rejectAfter(5000)]) break } catch( e ){} }

Si debes saber:

doSomething está enviando información de estado.

la promise está esperando la interacción del usuario.

*) Parte del propósito de este código es mostrar/demostrar a otros cómo se espera que funcionen las cosas. Así que estoy buscando la solución más clara en este nivel de implementación.

over 4 years ago · Santiago Trujillo
4 Respostas
Responde à pergunta

0

Modificación menor de su idea para que funcione mejor:

 const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); async function waitAndDo(promise) { let resolved = false; const waitFor = promise .then((result) => resolved = true); while(!resolved) { doSomething(); await Promise.race([waitFor, sleep(5000)]); } }
  1. La función acepta una promesa y estará funcionando hasta que se resuelva.
  2. La promesa waitFor finalizará después de que se cumpla y se resolved la promise actualizada a true .
  3. El bucle while puede repetirse hasta que la variable resolved se establezca en true . En ese caso, el ciclo terminará y la ejecución continuará después de él.
  4. Dentro del bucle, Promise.race() se asegurará de que dejará de esperar tan pronto como se resuelva la promesa o expire el sueño. Lo que sea que venga primero.

Por lo tanto, tan pronto como se resuelve la promesa, el controlador .then() se activa primero y se resolved las actualizaciones. El await Promise.race(); terminará la espera después y el bucle while no se ejecutará de nuevo, ya que resolved ahora es true .

over 4 years ago · Santiago Trujillo Relatório

0

Parece que simplemente usaría algún tipo de intervalo y lo mataría cuando se cumpliera la promesa.

 const updateMessage = (fnc, ms, runInit) => { if (runInit) fnc(); const timer = window.setInterval(fnc, ms); return function () { console.log('killed'); timer && window.clearTimeout(timer); } } const updateTime = () => { document.getElementById("out").textContent = Date.now(); } const updateEnd = updateMessage(updateTime, 100, true); new Promise((resolve) => { window.setTimeout(resolve, Math.floor(Math.random()*5000)); }).then(updateEnd);
 <div id="out"></div>

over 4 years ago · Santiago Trujillo Relatório

0

Como alternativa a la respuesta muy razonable de VLAZ, puede evitar el centinela booleano separado haciendo que su función de suspensión devuelva algún tipo de valor de retorno de centinela único que indique el tiempo de espera. Symbol es exactamente el tipo de objeto ligero y único para este caso de uso.

 function sleepPromise(ms, resolveWith) { return new Promise(resolve => { setTimeout(resolve, ms, resolveWith); }); } const inputPromise = new Promise( resolve => document.getElementById("wakeUp").addEventListener("click", resolve)); async function yourFunction() { const keepSleeping = Symbol("keep sleeping"); do { /* loop starts here */ console.log("Sleeping..."); /* loop ends here */ } while (await Promise.race([inputPromise, sleepPromise(3000, keepSleeping)]) === keepSleeping); console.log("Awake!"); } yourFunction();
 <button id="wakeUp">Wake up</button>

over 4 years ago · Santiago Trujillo Relatório

0

Un enfoque sería esperar el resultado de la promesa, asumiendo que es un valor verdadero 1 :

 const promise = someTask(); let result = undefined; while (!result) { doSomething(); result = await Promise.race([ promise, // resolves to an object sleep(5000), // resolves to undefined ]); }

1: y si no lo es, .then(_ => true) a la promise , o haga que sleep se cumpla con un valor especial que pueda distinguir de todo lo que someTask podría devolver (como el símbolo en la respuesta de Jeff).

También funciona bien con un bucle do - while , el result dado siempre está indefinido al principio:

 const promise = someTask(); let result = undefined; do { doSomething(); result = await Promise.race([ promise, // resolves to an object sleep(5000), // resolves to undefined ]); } while (!result);

Una desventaja aquí es que si doSomething() lanza una excepción, la promesa nunca se espera y puede causar un bloqueo de rechazo no controlado cuando la tarea falla.


Otro enfoque sería no usar un bucle, sino un intervalo de la vieja escuela:

 const i = setInterval(doSomething, 5000); let result; try { result = await someTask(); } finally { clearInterval(i); }

Una desventaja aquí es que doSomething no se llama inmediatamente sino solo después de 5 segundos por primera vez. Además, si doSomething arroja una excepción, la aplicación se bloqueará instantáneamente. Todavía podría ser un buen enfoque si no espera que doSomething arroje (o maneje cada excepción en la devolución de llamada setInterval y espere que el "bucle" continúe).


El enfoque "adecuado" que reenviará todas las excepciones tanto de someTask() como de doSomething() podría verse así:

 let done = false; const result = await Promise.race([ (async() => { while (!done) { doSomething(); await sleep(5000) } })(), someTask().finally(() => { done = true; }), ]);

(En lugar de .finally() , también puede envolver Promise.race en un try , finally , como en el enfoque dos).

La única pequeña desventaja en comparación con el enfoque dos es que sleep(5000) seguirá ejecutándose y no se cancelará de inmediato cuando finalice someTask (aunque el result esté disponible de inmediato), lo que podría impedir que su programa salga tan pronto como lo desee.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda