web-dev-qa-db-fra.com

Est-il possible d'intercepter des exceptions émises dans un rappel asynchrone JavaScript?

Existe-t-il un moyen de détecter les exceptions dans les rappels JavaScript? Est-ce même possible?

Uncaught Error: Invalid value for property <address>

Voici le 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);
}​
56
anewb

La raison pour laquelle rien ne sera compris dans votre exemple est qu’une fois le rappel geocode() appelé, le bloc try/catch est terminé. Par conséquent, le rappel geocode() est exécuté en dehors de la portée du bloc try et ne peut donc pas être attrapé par lui. 

Autant que je sache, il n’est pas possible d’attraper les exceptions lancées dans les rappels JavaScript (du moins, pas de manière simple).

64
Daniel Vassallo

Oui, vous pouvez remplacer le comportement par défaut 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; 
};
39
Jivings

Vous pouvez en effet intercepter des exceptions déclenchées par une fonction de rappel JavaScript.

La clé consiste à configurer le bloc try/catch dans le code de rappel, car tous les blocs try/catch situés en dehors du code de rappel auront déjà été fermés au moment de l'exécution du code de rappel. Ainsi, bien que votre bloc try/catch ci-dessus ne puisse pas intercepter les exceptions émises lors de l'appel de la fonction de rappel, vous pouvez néanmoins procéder de la manière suivante:

// 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!");
      }
   }
);

et vous serez en mesure de capturer l'exception quand elle est lancée. Je n'étais pas sûr à 100% que ce soit le cas ou non, alors j'ai écrit un code de test pour vérifier. L'exception est capturée comme prévu sur Chrome 19.0.1055.1 dev.

15
Justin Houk

J'ai détecté l'erreur en appliquant un correctif aux journaux de la console.

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);
    }
}
1
Karan Bhandari

Voici mon approche:

// 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 :(
}
0
Martin Konecny