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

221
Vistas
¿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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar

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 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