2010-09-09 16 views
51

Czy istnieje sposób na wychwycenie wyjątków w wywołaniach JavaScript? Czy to możliwe?Czy można przechwytywać wyjątki zgłaszane w wywołaniu asynchronicznym JavaScript?

Uncaught Error: Invalid value for property <address> 

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

Odpowiedz

61

Powodem nie będzie nic w przykładzie złapać dlatego po geocode() zwrotna jest wywoływana, blok try/catch jest skończona. Dlatego wywołanie zwrotne geocode() jest wykonywane poza zakresem bloku try, a zatem nie można go od niego odjąć.

O ile mi wiadomo, nie jest możliwe wychwycenie wyjątków zgłaszanych przez wywołania zwrotne JavaScript (przynajmniej nie w prosty sposób).

+8

@anewb, dać Daniels odebrać √ – sbartell

+1

Pytanie brzmi: "Czy to w ogóle możliwe?" i to jest dobra odpowiedź, @BlakeRegalia. – mqsoh

+1

Logiczne i właśnie to, czego się obawiałem, gdy zacząłem patrzeć na ten problem. Utknąłem w przypadku, gdy kod, którego nie kontroluję, rzuca wyjątek, który muszę złapać, ale nie mogę, ponieważ jest to asynchroniczne ... –

14

Można rzeczywiście przechwytywać wyjątki uruchamiane przez funkcję zwrotną JavaScript.

Kluczem jest ustawienie bloku try/catch w obrębie kodu wywołania zwrotnego, ponieważ wszelkie bloki try/catch poza kodem wywołania będą już zakończone przed wykonaniem kodu zwrotnego. Tak więc w czasie, gdy blok try/catch powyżej nie będzie w stanie wychwycić wszystkie wyjątki, które trafiają, gdy funkcja zwrotna jest wywoływana, wciąż można zrobić coś takiego:

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

i będziesz w stanie przechwytywać wyjątku kiedy zostanie rzucony. Nie byłem w 100% pewny, czy tak jest, czy nie, więc napisałem kod testowy do weryfikacji. Wyjątek jest przechwytywany zgodnie z oczekiwaniami w Chrome 19.0.1055.1.

+2

Co się stanie, jeśli wyjątek nie został zgłoszony w kodzie zwrotnym, ale raczej przez asynchroniczny funkcjonować. Funkcja async wyrzuca błąd w pewnym momencie przetwarzania, co oznacza, że ​​żaden z naszych prób catch nie będzie go przechwytywał. Obecnie mam do czynienia z tym problemem. Daj mi znać, co możesz zrobić. – faizan

+0

** Ta odpowiedź jest błędna **. Rzut jest wykonywany przez funkcję 'a.b.c.f()' w asynchronicznym wątku. Innymi słowy, twoje wywołanie zwrotne nie zostanie wywołane, ponieważ wystąpił błąd przed twoim oddzwonieniem. Ta odpowiedź będzie właściwa tylko wtedy, gdy osoba wdrażająca podejmie decyzję o przeniesieniu tego błędu do funkcji zwrotnej, gdy funkcja zwrotna współpracuje, wywołując zaimplementowaną funkcję, która spowodowałaby błąd dla funkcji zwrotnej. – Pacerier

+0

@Pacerier pytanie było, czy możesz złapać wyjątek w rzeczywistym wywołaniu zwrotnym. Jeśli callback nie jest wywoływany, to wykracza to poza zakres tego pytania. – Brain2000

37

Tak, można zastąpić domyślne zachowanie 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

mam wykryty błąd przez małpy łatanie dzienniki konsoli.

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

Oto moje podejście:

// 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 :(
} 
Powiązane problemy