web-dev-qa-db-ja.com

JavaScript非同期コールバックでスローされた例外をキャッチすることは可能ですか?

JavaScriptコールバックで例外をキャッチする方法はありますか?それも可能ですか?

Uncaught Error: Invalid value for property <address>

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

サンプルで何もキャッチされない理由は、geocode()コールバックが呼び出されると、_try/catch_ブロックが終了するためです。したがって、geocode()コールバックはtryブロックのスコープ外で実行されるため、キャッチできません。

私の知る限り、JavaScriptコールバックでスローされた例外をキャッチすることはできません(少なくとも、簡単な方法ではありません)。

69
Daniel Vassallo

はい、 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; 
};
38
Jivings

JavaScriptコールバック関数内で発生する例外を実際にキャッチできます。

重要なのは、try/catchコールバックコード内のブロック、任意のtry/catchコールバックコードの外側のブロックは、コールバックコードが実行されるまでに既に終了しています。 try/catch上記のブロックでは、コールバック関数が呼び出されたときにスローされる例外をキャッチできませんが、次のようなことができます。

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

そして、例外がスローされたときにキャプチャすることができます。私はそれがそうであるかどうかを100%確信していなかったので、検証するためにいくつかのテストコードを書きました。 Chrome 19.0.1055.1 dev。

15
Justin Houk

猿がコンソールログにパッチを当てることでエラーを検出しました。

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

私のアプローチは次のとおりです。

// 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