2010-09-09 11 views
51

¿Hay alguna manera de detectar excepciones en las devoluciones de llamada de JavaScript? ¿Es posible?¿Es posible detectar excepciones lanzadas en una devolución de llamada asíncrona JavaScript?

Uncaught Error: Invalid value for property <address> 

Aquí es 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); 
}​ 

Respuesta

61

La razón de que no va a coger cualquier cosa en su ejemplo se debe a que una vez que la devolución de llamada geocode() se llama, el bloque try/catch ha terminado. Por lo tanto, la devolución de llamada geocode() se ejecuta fuera del alcance del bloque try y, por lo tanto, no es detectable.

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

+8

@anewb, dan Daniels responder a una √ – sbartell

+1

La pregunta es: "¿Es posible?" y esta es una buena respuesta, @BlakeRegalia. – mqsoh

+1

Lógico y justo lo que temía cuando comencé a mirar este problema. Estoy atascado con un caso en el que el código que no control arroja una excepción que necesito detectar, pero no puedo porque es asincrónico ... –

14

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. Así, mientras que su bloque try/catch anterior no será capaz de atrapar las excepciones que se tiran cuando la función de devolución de llamada, todavía se 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 usted será capaz de capturar la excepción cuando es arrojado 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.

+2

¿Qué sucede si la excepción no se lanzó en el código de devolución de llamada sino en la asincrónica? función. La función asíncrona arroja un error en algún punto de su procesamiento, lo que significa que ninguno de nuestros intentos de captura lo detectará. Actualmente estoy enfrentando este problema. Déjame saber lo que piensas que se puede hacer. – faizan

+0

** Esta respuesta es incorrecta **. El lanzamiento se realiza mediante la función 'a.b.c.f()' en el hilo asíncrono. En otras palabras, su devolución de llamada ni siquiera se llama porque hay un error antes de su devolución de llamada. Esta respuesta solo será correcta si el implementador decide transferir ese error a su función de devolución de llamada cuando su función de devolución de llamada coopera llamando a la función implementada que arrojaría el error a su función de devolución de llamada. – Pacerier

+0

@Pacerier, la pregunta es si puede detectar una excepción en la devolución de llamada real. Si no se llama a la devolución de llamada, eso está fuera del alcance de esta pregunta. – Brain2000

37

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; 
}; 
1

he detectado el error mono parchear 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); 
    } 
} 
0

Aquí es 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 :(
} 
Cuestiones relacionadas