【问题标题】:Throw from jQuery.ajax callback is not caught?jQuery.ajax 回调中的抛出未被捕获?
【发布时间】:2012-12-09 18:08:05
【问题描述】:

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

【问题讨论】:

    标签: jquery ajax asynchronous try-catch throw


    【解决方案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" );
        });
    }
    

    【讨论】:

    • 谢谢阿伦,很抱歉回复晚了(圣诞节和所有..)我得稍微研究一下你的例子,但我最初的反应是为什么这会对我有帮助,我不看对于 ajax 调用的响应中的 try/catch,但我正在寻找将 ajax 调用包装在 throw/catch 中并从它的响应中捕获任何 throw。
    • @JochemVanDerSpek 它不会像 ajax 调用那样工作。 ajax 调用是异步调用,这意味着我们不知道请求何时完成。
    • 对不起,但这不是异步的意思。任何通话的“结束”都可能是不确定的。异步意味着它在不同的线程中执行,因此,try 在一个线程中,而 throw 在另一个线程中。这是无法调和的。请参阅 user1321471 的回答。
    • @JochemVanDerSpek 抱歉,Javascript 主要被视为单线程应用程序,即在任何时间点都只会执行一段脚本。因此,这与在另一个线程中执行的异步调用无关。 nczonline.net/blog/2010/08/10/what-is-a-non-blocking-script / stackoverflow.com/questions/7575589/… / stackoverflow.com/questions/6659108/…
    • 感谢您的链接! 但是现在我又回到不明白为什么没有办法做我想做的事了。我有两个问题要问你,你能想出任何其他方法来从 ajax 异步调用的回调中捕获抛出吗?您是否知道任何详细解释浏览器实现和执行模型的集中式资源(又名一本书)?我真的很想知道这里的细节..
    猜你喜欢
    • 2023-02-06
    • 2019-01-15
    • 1970-01-01
    • 2012-02-03
    • 1970-01-01
    • 2015-06-29
    • 2018-08-09
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多