我在Ajax回调中从回调中捕获抛出时遇到一些麻烦。我做了一个最小的测试用例here(下面的代码)。
在init()
函数中,我创建了一个类ResourceLoader
的新对象,并尝试获取http://www.jvanderspek.com。通过$ .ajax。这成功并调用ResourceLoader.prototype.onDone
函数。现在为了争论我想在那里抛出一个错误,并在我的调用树的顶部,在init();
函数中捕获它,但是唉,抛出没有被捕获。现在,这可能与Ajax在不同的线程中执行有关,并且当执行已经在try块之外时调用throw,但是我该如何解决它呢?也许我误解了原因,但接下来的问题是,为什么会发生这种情况呢?
<html>
<head>
<title>testbed</title>
<script src="http://code.jquery.com/jquery-1.8.3.js" type="text/javascript"></script>
</head>
<body onload="init();">
</body>
<script type="text/javascript">
init = function() {
ResourceLoader = function(){}
ResourceLoader.prototype.load = function(){
var done = $.proxy(this.onDone, this);
$.ajax({
url: "http://www.jvanderspek.com",
}).done(done);
}
ResourceLoader.prototype.onDone = function() {
console.log( "onDone");
throw(new Error());
}
var rl = new ResourceLoader();
try {
rl.load();
}
catch(error){
window.alert( "Error caught" );
}
}
</script>
</html>
答案 0 :(得分:1)
这是因为Ajax使用异步执行模型。
在进行ajax调用之后的异步调用中,代码的执行将继续,而不会等待响应返回。当响应从服务器返回时,将调用成功/失败回调。
在您的情况下,rl.load();
调用将在发送到服务器的请求后立即返回(即:在抛出错误之前),这就是catch块无法正常工作的原因。
问题的一个可能的脏解决方案是将附加参数async: false
传递给ajax调用。但它没有达到Ajax调用的全部目的,因为它会阻止用户体验直到ajax调用完成。 我没有测试过这个解决方案,可能你可以尝试一下。 我不会向任何人推荐这个,但作为理解Ajax的一部分,你可以试试这个。
另一个解决方案是将错误回调传递给load()
方法,并在该回调失败时执行您想要的操作。
例如:
init = function() {
ResourceLoader = function(){}
ResourceLoader.prototype.load = function(errorCallback){
var done = $.proxy(this.onDone, this);
$.ajax({
url: "http://www.jvanderspek.com",
}).done(function(){
try{
console.log( "onDone");
throw(new Error());
}catch(error){
errorCallback(error)
}
});
}
var rl = new ResourceLoader();
rl.load(function(error){
window.alert( "Error caught" );
});
}