抛出jQuery.ajax回调是不是被抓住了?

时间:2012-12-22 11:17:07

标签: jquery ajax asynchronous try-catch throw

我在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>

1 个答案:

答案 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" );
    });
}