provocar - ¿Es posible detectar excepciones lanzadas en una devolución de llamada asíncrona JavaScript?
try and catch java script (5)
¿Hay alguna forma de detectar excepciones en las devoluciones de llamada de JavaScript? ¿Es posible?
Uncaught Error: Invalid value for property <address>
Aquí está el jsfiddle: http://jsfiddle.net/kjy112/yQhhy/
try {
// this will cause an exception in google.maps.Geocoder().geocode()
// since it expects a string.
var zipcode = 30045;
var map = new google.maps.Map(document.getElementById(''map_canvas''), {
zoom: 5,
center: new google.maps.LatLng(35.137879, -82.836914),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// exception in callback:
var geo = new google.maps.Geocoder().geocode({ ''address'': zipcode },
function(geoResult, geoStatus) {
if (geoStatus != google.maps.GeocoderStatus.OK) console.log(geoStatus);
}
);
} catch (e) {
if(e instanceof TypeError)
alert(''TypeError'');
else
alert(e);
}
Aquí está mi enfoque:
// the purpose of this wrapper is to ensure that any
// uncaught exceptions after a setTimeout still get caught
function callbackWrapper(func) {
return function() {
try {
func();
} catch (err) {
// callback will reach here :)
// do appropriate error handling
console.log("error");
}
}
}
try {
setTimeout(callbackWrapper(function() {throw "ERROR";}), 1000);
} catch (err) {
// callback will never reach here :(
}
De hecho, puede detectar excepciones que se activan dentro de una función de devolución de llamada de JavaScript.
La clave es configurar el bloque try/catch
dentro del código de devolución de llamada, ya que cualquier bloque try/catch
fuera del código de devolución de llamada ya habrá salido antes de que se ejecute el código de devolución de llamada. Entonces, mientras su bloque try/catch
arriba no podrá capturar ninguna excepción que se lanza cuando se llama a la función de devolución de llamada, aún puede hacer algo como esto:
// this will cause an exception ing google.maps.Geocoder().geocode()
// since it expects a string.
var zipcode = 30045;
var map = new google.maps.Map(document.getElementById(''map_canvas''), {
zoom: 5,
center: new google.maps.LatLng(35.137879, -82.836914),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// exception in callback:
var geo = new google.maps.Geocoder().geocode({ ''address'': zipcode },
function(geoResult, geoStatus) {
try {
if (geoStatus != google.maps.GeocoderStatus.OK) console.log(geoStatus);
} catch(e){
alert("Callback Exception caught!");
}
}
);
y podrás capturar la excepción cuando se lanza. No estaba 100% seguro de si ese sería el caso o no, así que escribí un código de prueba para verificarlo. La excepción se captura como se esperaba en Chrome 19.0.1055.1 dev.
He detectado el error al poner parches en los registros de la consola.
if(window.console && console.error){
var old = console.error;
console.error = function(){
if(arguments[0].indexOf(''Google Maps API error'')!=-1){
alert(''Bad Google API Key ''+ arguments[0]);
}
Array.prototype.unshift.call(arguments);
old.apply(this, arguments);
}
}
La razón por la que no detectará nada en su ejemplo es porque una vez que se llama a la devolución de llamada geocode()
, el bloque try/catch
termina. Por lo tanto, la devolución de llamada geocode()
se ejecuta fuera del alcance del bloque try
y, por lo tanto, no es capturable por él.
Por lo que yo sé, no es posible detectar las excepciones lanzadas en las devoluciones de llamada de JavaScript (al menos, no de manera directa).
Sí, puede anular el comportamiento predeterminado de window.onerror :
window.onerror = function(message, file, lineNumber) {
// all errors will be caught here
// you can use `message` to make sure it''s the error you''re looking for
// returning true overrides the default window behaviour
return true;
};