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

222
Views
¿Alguna forma de hacer que se rechace una promesa si tiene un error no detectado?

Es fácil olvidarse de usar try/catch en una función asíncrona o no detectar todos los posibles errores cuando se trabaja con promesas. Esto puede causar una "espera" interminable si la Promesa nunca se resuelve ni se rechaza.

¿Hay alguna forma (como a través de un proxy o alterando el constructor de promesas) para hacer que se rechace una función asíncrona u otras promesas si hay un error no detectado? A continuación se muestra un caso generalizado. Estoy buscando alguna forma de superar la "espera" (como en "p" debe rechazarse cuando se produce el error) sin corregir "badPromise".

 async function badPromise() { const p = new Promise((res) => { delayTimer = setTimeout(() => { console.log('running timeout code...'); if (1 > 0) throw new Error('This is NOT caught!'); // prevents the promise from ever resolving, but may log an error message to the console res(); }, 1000); }); return p; } (async () => { try { console.log('start async'); await badPromise(); console.log('Made it to the end'); // never get here } catch (e) { console.error('Caught the problem...', e); // never get here } })();```
about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

Las promesas ya se rechazan en el caso de un error sincrónico no detectado:

  • en un constructor Promise , para errores síncronos (lanzados)

    Si se arroja un error en el ejecutor, la promesa se rechaza.

  • en las funciones onFulfilled y onRejected , como en then y catch

    Si una función de controlador: [...] arroja un error, la promesa devuelta por then se rechaza con el error arrojado como su valor.

  • en funciones async

    Valor devuelto: una Promise que se resolverá con el valor devuelto por la función asíncrona, o se rechazará con una excepción lanzada o no detectada dentro de la función asíncrona.

Su problema aquí no es que Promise no maneje errores no detectados, es fundamentalmente porque su error es asíncrono : en lo que respecta a Promise, su función de ejecución es una pequeña función exitosa que llama a setTimeout . En el momento en que su controlador setTimeout se ejecuta y falla, lo hace con su propia pila que no está relacionada con el objeto Promise o su función; no existe nada relacionado con badPromise o p dentro de su controlador setTimeout que no sea la referencia res que el controlador incluye a través del cierre. Al igual que en la pregunta " Manejar el error de setTimeout ", las técnicas para detectar errores en los controladores de setTimeout implicaron editar o ajustar el controlador, y según la especificación HTML para temporizadores , paso 9.2, no hay oportunidad de detectar o intercalar un caso de error para la invocación. de la función pasada a setTimeout .

Aparte de editar badPromise , no hay casi nada que puedas hacer.


(La única alternativa que se me ocurre es modificar/sobrescribir tanto el constructor Promise como el método setTimeout en secuencia, envolviendo el método del constructor Promise para guardar los parámetros de resolve / reject y luego envolviendo el método setTimeout global para envolver el controlador setTimeout con el try / catch que invoca el parámetro de reject recién guardado. Debido a la fragilidad de cambiar ambos servicios globales, desaconsejo soluciones como esta).

about 4 years ago · Juan Pablo Isaza Report

0

El problema subyacente es que las devoluciones de llamada del temporizador se ejecutan como código de nivel superior y la única forma de detectar errores en ellas es escuchar eventos de error globales. Aquí hay un ejemplo del uso de un controlador global para detectar tales errores, pero tiene problemas que discutiré debajo del código:

 "use strict"; let delayTimer; // declare variable async function badPromise() { const p = new Promise((res) => { let delayTimer = setTimeout(() => { // declare variable!!! console.log('running timeout code...'); if (1 > 0) throw new Error('This is NOT caught!'); // prevents the promise from ever resolving, but may log an error message to the console res(); }, 1000); }); return p; } (async () => { let onerror; let errorArgs = null; let pError = new Promise( (res, rej)=> { onerror = (...args) => rej( args); // error handler rejects pError window.addEventListener("error", onerror); }) .catch( args => errorArgs = args); // Catch handler resolves with error args // race between badPromise and global error await Promise.race( [badPromise(), pError] ); window.removeEventListener("error", onerror); // remove global error handler console.log("Made it here"); if( errorArgs) { console.log(" but a global error occurred, arguments array: ", errorArgs); } })();

Problemas

  • El código se escribió sin importar lo que se pasa a un controlador de errores global agregado mediante addEventListener ; puede obtener diferentes argumentos si usa window.onerror = errorHandler .
  • La carrera de la promesa se puede ganar con cualquier evento de error que aparezca en la window del ejemplo. No es necesario que se haya generado en la llamada badPromise() .
  • Si varias llamadas a badPromise están activas al mismo tiempo, la captura de errores globales no le indicará qué llamada badPromise error.

Por lo tanto badPromise es realmente malo y debe manejarse con guantes de seda. Si realmente no puede arreglarlo, es posible que deba asegurarse de que solo tenga una llamada pendiente y que no esté haciendo nada más que pueda generar un error global al mismo tiempo. No puedo comentar si esto es posible en su caso.

Alternativa

Una alternativa más genérica puede ser iniciar un temporizador antes de llamar a badPromise y usarlo para agotar el tiempo de espera del estado pendiente de la promesa devuelta;

 let timer; let timeAllowed = 5000; let timedOut = false; let timeout = new Promise( res => timer = setTimeout(res, timeAllowed)) .then( timedOut = true); await Promise.race( [badPromise(), timeout]) clearTimer( timer); console.log( "timed out: %s", timedOut);
about 4 years ago · Juan Pablo Isaza Report

0

Puede haber una manera de hacer esto, pero en su caso, creo que realmente desea usar la función de reject dentro de su Promesa en lugar de throw . Eso es realmente para lo que es el rechazo.

 async function badPromise() { const p = new Promise((res, reject) => { delayTimer = setTimeout(() => { console.log('running timeout code...'); if (1 > 0) { reject('This is NOT caught!'); return; } res(); }, 1000); }); return p; } (async () => { try { console.log('start async'); await badPromise(); console.log('Made it to the end'); // never gets here } catch (e) { console.error('Caught the problem...', e); // should work now } })();
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!