promises - then javascript
Cómo atrapar una excepción no capturada en Promise (5)
Actualización, las promesas nativas ahora hacen lo siguiente en la mayoría de los navegadores:
window.addEventListener("unhandledrejection", function(promiseRejectionEvent) {
// handle error here, for example log
});
Estábamos discutiendo esto el otro día.
Así es como harías esto con bluebird:
window.onpossiblyunhandledexception = function(){
window.onerror.apply(this, arguments); // call
}
window.onerror = function(err){
console.log(err); // logs all errors
}
Con Bluebird también es posible usar
Promise.onPossiblyUnhandledRejection
.
Las llamadas para
done
no son necesarias ya que la biblioteca detectará el rechazo no controlado a diferencia de Q (ACTUALIZACIÓN 2016: ahora escribí el código para Q y lo hace).
En cuanto a las promesas nativas , eventualmente informarán a window.onerror o a un nuevo controlador, pero el proceso de especificación aún no se ha completado; puede seguirlo aquí .
¿Hay alguna manera de detectar globalmente todas las excepciones, incluidas las excepciones de Promise? Ejemplo:
window.onerror = function myErrorHandler(errorMsg, url, lineNumber) {
alert("Error occured: " + errorMsg);//or any message
return false;
}
var myClass = function(){
}
var pr = new Promise(function(resolve, react){
var myInstance = new myClass();
myInstance.undefinedFunction(); // this will throw Exception
resolve(myInstance);
});
pr.then(function(result){
console.log(result);
});
// i know right will be this:
// pr.then(function(result){
// console.log(result);
// }).catch(function(e){
// console.log(e);
// });
Este script morirá silenciosamente sin error. Nada en Firebug.
Mi pregunta es si cometo un error y olvidé detectarlo, ¿hay alguna forma de detectarlo globalmente?
En Node.js, puede usar:
process.on(''unhandledRejection'', (reason, promise) => {
console.error(`Uncaught error in`, promise);
});
La mayoría de las implementaciones prometedoras actualmente no proporcionan el tipo de funcionalidad a la que se refiere, pero una serie de bibliotecas prometedoras de terceros (que incluyen
Q
y
bluebird
) proporcionan un método
done()
que detectará y arrojará cualquier error no detectado, lo que los generará a la consola
( Editar: vea la respuesta de Benjamin Gruenbaum sobre las características de Bluebird para manejar excepciones no capturadas)
Entonces, si tiene eso, solo debe seguir la regla general de que cualquier promesa que use debe devolverse o terminarse con
.done()
:
pr.then(function(result){
console.log(result);
})
.done();
Para citar de la referencia Q API:
La regla de oro del uso
done
frente al uso es:return
su promesa a otra persona o, si la cadena termina con usted, llame aldone
para finalizarla. Terminar concatch
no es suficiente porque el controlador decatch
puede generar un error.
Me doy cuenta de que esto todavía requiere un poco de trabajo extra y aún puede olvidarse de hacer esto, pero es una mejora sobre tener que
.catch()
y manejar explícitamente cada error, especialmente por la razón señalada anteriormente.
Si está escribiendo código que se puede ejecutar tanto en un navegador como en un entorno Node.js, puede envolver su código en una función de ejecución automática como esta:
var isNode = (typeof process !== ''undefined'' && typeof process.on !== ''undefined'');
(function(on, unhandledRejection) {
// PUT ANY CODE HERE
on(unhandledRejection, function(error, promise) {
console.error(`Uncaught error in`, promise);
});
// PUT ANY CODE HERE
})(
isNode ? process.on.bind(process) : window.addEventListener.bind(window),
isNode ? "unhandledRejection" : "unhandledrejection"
);
¿Qué pasaría si usa este código?
-
Si lo ejecuta en un entorno Node.js, su controlador se adjuntará al objeto de proceso y se ejecutará cuando tenga una excepción no detectada en una promesa.
-
Si lo ejecuta en un entorno de navegador, su controlador se adjuntará al objeto de ventana y se ejecutará cuando tenga una excepción no detectada en una promesa y su navegador admita el evento de
unhandledrejection
. -
Si lo ejecuta en un entorno de navegador sin soporte para el
unhandledrejection
, no podrá detectar su excepciónunhandledrejection
detectada y suunhandledrejection
eventos deunhandledrejection
controlado nunca se activará, pero no obtendrá ningún error si no hay excepciones no detectadas.
Si está utilizando Promise nativo, es bastante simple.
Solo necesita
.catch
este rechazo en algún lugar.
ajax(request).catch(function(rejected){
console.log(rejected);
});
Si no lo atrapo en alguna parte, la promesa no alcanzada seguirá apareciendo. Pero si lo atrapo en alguna parte ...