È ansible rilevare eccezioni generate in un callback async JavaScript?

C’è un modo per cogliere le eccezioni nei callback JavaScript? È ansible?

Uncaught Error: Invalid value for property 

Ecco il 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); }​ 

Il motivo per cui non catturerà nulla nel tuo esempio è perché una volta chiamato il callback geocode() , il blocco try/catch è finito. Pertanto, il callback geocode() viene eseguito al di fuori dell’ambito del blocco try e quindi non può essere catchable da esso.

Per quanto ne so, non è ansible rilevare le eccezioni generate nei callback JavaScript (almeno, non in modo diretto).

Sì, puoi sovrascrivere il comportamento predefinito di 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; }; 

È ansible infatti rilevare le eccezioni triggerste all’interno di una funzione di callback JavaScript.

La chiave è impostare il blocco try/catch all’interno del codice di richiamata, poiché qualsiasi blocco try/catch al di fuori del codice di richiamata sarà già uscito dal momento in cui viene eseguito il codice di richiamata. Quindi, mentre il tuo blocco try/catch sopra non sarà in grado di rilevare le eccezioni che vengono lanciate quando viene chiamata la funzione callback, puoi comunque fare qualcosa del genere:

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

e sarai in grado di catturare l’eccezione quando viene lanciata. Non ero sicuro al 100% se fosse così o no, quindi ho scritto un codice di prova per verificare. L’eccezione viene acquisita come previsto su Chrome 19.0.1055.1 dev.

Ho rilevato l’errore tramite la patch di scimmia sui registri della 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); } } 

Ecco il mio approccio:

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