2010-09-09 12 views
51

C'è un modo per rilevare le eccezioni nei callback JavaScript? È possibile?È possibile rilevare le eccezioni generate in un callback async JavaScript?

Uncaught Error: Invalid value for property <address> 

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

risposta

61

Il motivo per cui non prenderà nulla nel tuo esempio è perché una volta che il geocode() callback viene chiamata, il blocco try/catch è finita. Pertanto, la callback viene eseguita al di fuori dell'ambito del blocco try e quindi non può essere rilevata da esso.

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

+8

@anewb, danno Daniels rispondere a una √ – sbartell

+1

La domanda è: "E 'anche possibile?" e questa è una buona risposta, @BlakeRegalia. – mqsoh

+1

Logico e proprio quello che temevo quando ho iniziato a guardare questo problema. Sono bloccato con un caso in cui il codice che non controllo genera un'eccezione che devo catturare, ma non posso perché è asincrono ... –

14

È possibile infatti rilevare le eccezioni attivate all'interno di una funzione di callback JavaScript.

Il tasto consente di impostare il blocco try/catch all'interno del codice di richiamata, poiché qualsiasi blocco try/catch esterno al codice di richiamata sarà già uscito dal momento in cui viene eseguito il codice di richiamata. Così, mentre il tuo blocco try/catch di cui sopra non sarà in grado di catturare tutte le eccezioni che vengono gettati quando viene chiamata la funzione di callback, si può ancora fare qualcosa di simile:

// 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 sarete in grado di catturare l'eccezione quando viene lanciato. 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.

+2

Cosa succede se l'eccezione non è stata lanciata nel codice di richiamata ma piuttosto dall'async funzione. La funzione async genera un errore ad un certo punto della sua elaborazione, il che significa che nessuno dei nostri tentativi di cattura lo catturerà. Attualmente sto affrontando questo problema. Fammi sapere cosa pensi possa essere fatto. – faizan

+0

** Questa risposta è sbagliata **. Il lancio viene eseguito dalla funzione 'a.b.c.f()' nel thread asincrono. In altre parole, la richiamata non viene nemmeno chiamata perché c'è un errore prima della richiamata. Questa risposta sarà corretta solo se l'implementatore decide di trasferire tale errore alla funzione di callback quando la funzione di callback coopera chiamando la funzione implementata che invierà l'errore alla funzione di callback. – Pacerier

+0

@Pacerier la domanda è stata in grado di rilevare un'eccezione nel callback effettivo. Se callback non viene chiamato, questo non rientra nell'ambito di questa domanda. – Brain2000

37

Sì, è possibile ignorare 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; 
}; 
1

ho rilevato l'errore scimmia patch i log 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); 
    } 
} 
0

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 :(
} 
Problemi correlati