是否可以捕获 JavaScript 异步回调中抛出的异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3677783/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to catch exceptions thrown in a JavaScript async callback?
提问by anewb
Is there a way to catch exceptions in JavaScript callbacks? Is it even possible?
有没有办法在 JavaScript 回调中捕获异常?甚至有可能吗?
Uncaught Error: Invalid value for property <address>
Here is the jsfiddle: http://jsfiddle.net/kjy112/yQhhy/
这是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);
}?
回答by Daniel Vassallo
The reason it won't catch anything in your example is because once the geocode()callback is called, the try/catchblock is over. Therefore the geocode()callback is executed outside the scope of the tryblock and thus not catchable by it.
它不会在您的示例中捕获任何内容的原因是因为一旦geocode()调用回调,try/catch块就结束了。因此geocode()回调是在try块的范围之外执行的,因此不能被它捕获。
As far as I know, it is not possible to catch exceptions thrown in JavaScript callbacks (at least, not in any straightforward manner).
据我所知,不可能捕获 JavaScript 回调中抛出的异常(至少,不是以任何直接的方式)。
回答by Jivings
Yes, you can override the default behaviour of window.onerror:
是的,您可以覆盖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;
};
回答by Justin Houk
You can indeed catch exceptions that fire within a JavaScript callback function.
您确实可以捕获在 JavaScript 回调函数中触发的异常。
The key is to set up the try/catchblock within the callback code, as any try/catchblocks outside the callback code will have already exited by the time the callback code is executed. So while your try/catchblock 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:
关键是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!");
}
}
);
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.
并且您将能够在抛出异常时捕获该异常。我不是 100% 确定是否是这种情况,所以我写了一些测试代码来验证。在 Chrome 19.0.1055.1 dev 上按预期捕获异常。
回答by Karan Bhandari
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);
}
}
回答by roxxypoxxy
If you can use Promises and async/await, it can be solved as shown in sample code below:
如果可以使用 Promises 和 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);
}
回答by Martin Konecny
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 :(
}
回答by Uri Abramson
According to all answers, try/catch + callback is set on a different context but then - how would you explain this code try/catch working?
根据所有答案,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();

