0

我在从 Ajax 回调中的回调中捕获抛出时遇到了一些麻烦。我在这里做了一个最小的测试用例(下面的代码)。

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>
4

1 回答 1

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" );
    });
}
于 2012-12-22T11:19:51.013 回答