Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/436.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以捕获JavaScript异步回调中抛出的异常?_Javascript_Google Maps_Exception_Callback - Fatal编程技术网

是否可以捕获JavaScript异步回调中抛出的异常?

是否可以捕获JavaScript异步回调中抛出的异常?,javascript,google-maps,exception,callback,Javascript,Google Maps,Exception,Callback,有没有办法捕获JavaScript回调中的异常?有可能吗 Uncaught Error: Invalid value for property <address> 在您的示例中,它不会捕获任何内容的原因是,一旦调用了geocode()回调,try/catch块就结束了。因此,geocode()回调在try块的范围之外执行,因此它无法捕获 据我所知,捕获JavaScript回调中抛出的异常是不可能的(至少,不是以任何直接的方式)。您确实可以捕获JavaScript回调函数中触发的异常

有没有办法捕获JavaScript回调中的异常?有可能吗

Uncaught Error: Invalid value for property <address>

在您的示例中,它不会捕获任何内容的原因是,一旦调用了
geocode()
回调,
try/catch
块就结束了。因此,
geocode()
回调在
try
块的范围之外执行,因此它无法捕获


据我所知,捕获JavaScript回调中抛出的异常是不可能的(至少,不是以任何直接的方式)。

您确实可以捕获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开发版上按预期捕获异常。

是的,您可以覆盖以下默认行为:


我通过修补控制台日志检测到错误

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);
    }
}
以下是我的方法:

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

根据所有答案,try/catch+callback是在不同的上下文中设置的,但是-您如何解释这段代码try/catch的工作原理

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();

如果您可以使用Promissions和async/await,则可以解决此问题,如下面的示例代码所示:

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

@anewb,给Daniels一个答案√问题是“这可能吗?”这是一个很好的答案,@BlakeRegalia.Logical,这正是我开始研究这个问题时所担心的。我遇到了这样一种情况:我无法控制的代码抛出一个我需要捕获的异常,但我不能,因为它是异步的……如果异常不是在回调代码中抛出的,而是由异步函数抛出的,会发生什么。异步函数在其处理过程中的某个点抛出错误,这意味着我们的try-catch都不会捕获它。我目前正面临这个问题。让我知道你认为可以做什么。这个答案是错误的。抛出由异步线程中的
a.b.c.f()
函数完成。换句话说,您的回调甚至不会被调用,因为回调之前有一个错误。只有当您的回调函数通过调用实现的函数进行协作时,实现者决定将错误转移到您的回调函数时,这个答案才是正确的。@Pacerier问题是,您能否在实际回调中捕获异常。如果没有调用回调,那么这就超出了这个问题的范围。@Pacier接受的答案说“不可能捕获JavaScript回调中抛出的异常”也是错误的。因此,这个函数是一个有用的附加函数。它之所以有效,是因为您没有异步调用回调函数。如果您这样做(例如使用
setTimeout()
),它将失败。
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();
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);
}