Is it possible to catch exceptions thrown in a JavaScript async callback?

前端 未结 7 1181
春和景丽
春和景丽 2020-11-27 04:15

Is there a way to catch exceptions in JavaScript callbacks? Is it even possible?

Uncaught Error: Invalid value for property 

相关标签:
7条回答
  • 2020-11-27 04:45

    Yes, you can override the default behaviour of 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; 
    };
    
    0 讨论(0)
  • 2020-11-27 04:47

    If you can use Promises and async/await, it can be solved as shown in sample code below:

    async function geocode(zipcode) {
    
      return new Promise((resolve, reject) => {
    
        const g = new google.maps.Geocoder().geocode({ 'address': zipcode },  function(geoResult, geoStatus) {
          if (geoStatus != google.maps.GeocoderStatus.OK) {
            reject(new Error("Callback Exception caught"));
          } else {
            resolve(g);
          };
    
        });
      });
    }
    
    try {
      // ...
    
      // g will be an instance of new google.maps.Geocoder().geocode..
      // you can resolve with desired variables
      const g = await geocode(zipcode);
    
      // ...
    } catch( e ) {
      console.log(e);
    }
    
    0 讨论(0)
  • 2020-11-27 04:56

    You can indeed catch exceptions that fire within a JavaScript callback function.

    The key is to set up the try/catch block within the callback code, as any try/catch blocks outside the callback code will have already exited by the time the callback code is executed. So while your try/catch block above won't be able to catch any exceptions that get thrown when the callback function is called, you can still do something like this:

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

    and you'll be able to capture the exception when it is thrown. I wasn't 100% sure whether that would be the case or not, so I wrote some test code to verify. The exception is captured as expected on Chrome 19.0.1055.1 dev.

    0 讨论(0)
  • 2020-11-27 05:00

    According to all answers, try/catch + callback is set on a different context but then - how would you explain this code try/catch working?

    function doSomeAsynchronousOperation(cb) {
      cb(3);
    }
    
    function myApiFunc() {
      /*
       * This pattern does NOT work!
       */
      try {
        doSomeAsynchronousOperation((err) => {
          if (err) {
            console.log('got here');
            throw err;
          }
    
        });
      } catch (ex) {
        console.log(ex);
      }
    }
    
    myApiFunc();
    
    0 讨论(0)
  • 2020-11-27 05:05

    Here's my approach:

    // 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 讨论(0)
  • 2020-11-27 05:07

    I have detected the error by monkey patching the console logs.

    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 讨论(0)
提交回复
热议问题