【问题标题】:How do I catch jQuery $.getJSON (or $.ajax with datatype set to 'jsonp') error when using JSONP?使用 JSONP 时如何捕获 jQuery $.getJSON(或数据类型设置为“jsonp”的 $.ajax)错误?
【发布时间】:2010-09-23 12:32:48
【问题描述】:

在 jQuery 中使用 JSONP 时是否可以捕获错误?我已经尝试了 $.getJSON 和 $.ajax 方法,但都不会捕获我正在测试的 404 错误。这是我尝试过的(请记住,这些都可以成功,但我想在失败时处理这种情况):

jQuery.ajax({
    type: "GET",
    url: handlerURL,
    dataType: "jsonp",
    success: function(results){
        alert("Success!");
    },
    error: function(XMLHttpRequest, textStatus, errorThrown){
        alert("Error");
    }
});

还有:

jQuery.getJSON(handlerURL + "&callback=?", 
    function(jsonResult){
        alert("Success!");
    });

我也尝试过添加 $.ajaxError 但这也没有用:

jQuery(document).ajaxError(function(event, request, settings){
   alert("Error");
});

提前感谢您的任何回复!

【问题讨论】:

  • 使用 'error:function(){}' 有什么问题??
  • 它没有触发。 (记住这是 JSONP)。

标签: javascript jquery jsonp


【解决方案1】:

Here 是我对类似问题的广泛回答。

代码如下:

jQuery.getJSON(handlerURL + "&callback=?", 
    function(jsonResult){
        alert("Success!");
    })
.done(function() { alert('getJSON request succeeded!'); })
.fail(function(jqXHR, textStatus, errorThrown) { alert('getJSON request failed! ' + textStatus); })
.always(function() { alert('getJSON request ended!'); });

【讨论】:

  • 我不明白为什么没有更多的赞成票。这显然是错误处理应该如何发生的。为什么接受的答案说“似乎不返回成功结果的 JSONP 请求永远不会触发任何事件、成功或失败”,而这显然不是真的?我不明白的事情。
  • 仔细阅读后我认为它必须这样做,2008 年的事情在 jQuery 中有点不同;)
  • @Daywalker 是的,从 JQuery 3.0 (api.jquery.com/jQuery.get) 开始,success/error/complete 方法已被弃用和删除
【解决方案2】:

似乎不返回成功结果的 JSONP 请求永远不会触发任何事件、成功或失败,无论好坏,这显然是设计使然。

在搜索他们的错误跟踪器后,a patch 可能是使用超时回调的可能解决方案。见bug report #3442。如果您无法捕获错误,您至少可以在等待一段合理的时间后超时。

【讨论】:

【解决方案3】:

检测 JSONP 问题

如果您不想下载依赖项,您可以自己检测错误状态。这很容易。

您只能通过使用某种超时来检测 JSONP 错误。如果在特定时间内没有有效的响应,则假设一个错误。不过,错误基本上可以是任何东西。

这是检查错误的简单方法。只需使用success 标志:

var success = false;

$.getJSON(url, function(json) {
    success = true;
    // ... whatever else your callback needs to do ...
});

// Set a 5-second (or however long you want) timeout to check for errors
setTimeout(function() {
    if (!success)
    {
        // Handle error accordingly
        alert("Houston, we have a problem.");
    }
}, 5000);

正如 cmets 中提到的黎明骑士,你也可以使用 clearTimeout 代替:

var errorTimeout = setTimeout(function() {
    if (!success)
    {
        // Handle error accordingly
        alert("Houston, we have a problem.");
    }
}, 5000);

$.getJSON(url, function(json) {
    clearTimeout(errorTimeout);
    // ... whatever else your callback needs to do ...
});

为什么?继续阅读...


简而言之,JSONP 的工作原理如下:

JSONP 不像常规 AJAX 请求那样使用 XMLHttpRequest。相反,它将<script> 标记注入页面,其中“src”属性是请求的 URL。响应的内容被包装在一个 Javascript 函数中,然后在下载时执行。

例如。

JSONP 请求:https://api.site.com/endpoint?this=that&callback=myFunc

Javascript 会将此脚本标签注入 DOM:

<script src="https://api.site.com/endpoint?this=that&callback=myFunc"></script>

&lt;script&gt; 标签添加到DOM 时会发生什么?显然,它会被执行。

因此假设对该查询的响应产生如下 JSON 结果:

{"answer":42}

对于浏览器来说,这与脚本的源代码相同,因此它会被执行。但是当你执行这个时会发生什么:

<script>{"answer":42}</script>

嗯,没什么。它只是一个对象。它不会被存储、保存,也不会发生任何事情。

这就是 JSONP 请求将其结果包装在一个函数中的原因。必须支持 JSONP 序列化的服务器会看到您指定的 callback 参数,并改为返回:

myFunc({"answer":42})

然后这会被执行:

<script>myFunc({"answer":42})</script>

... 这更有用。在这种情况下,您的代码中的某处是一个名为 myFunc 的全局函数:

myFunc(data)
{
    alert("The answer to life, the universe, and everything is: " + data.answer);
}

就是这样。这就是 JSONP 的“魔力”。然后构建超时检查非常简单,如上所示。发出请求,然后立即开始超时。 X 秒后,如果您的标志仍未设置,则请求超时。

【讨论】:

  • 你也可以使用jsonpFailCheck = setTimeout(...),然后你可以使用success=true而不是clearTimeout(jsonpFailCheck)
【解决方案4】:

我知道这个问题有点老了,但我没有看到一个可以简单解决问题的答案,所以我想我会分享我的“简单”解决方案。

$.getJSON("example.json", function() {
      console.log( "success" );
}).fail(function() { 
      console.log( "error" ); 
}); 

我们可以简单地使用.fail() 回调来检查是否发生了错误。

希望这会有所帮助:)

【讨论】:

【解决方案5】:

如果您与提供者合作,您可以发送另一个查询字符串参数作为出现错误时回调的函数。

?callback=?&error=?

这被称为 JSONPE,但它根本不是事实上的标准。

然后提供程序将信息传递给错误函数以帮助您进行诊断。

但对通信错误没有帮助 - 必须更新 jQuery 以在超时时回调错误函数,如 Adam Bellaire 的回答。

【讨论】:

    【解决方案6】:

    现在好像这样:

    jQuery(document).ajaxError(function(event, request, settings){
       alert("Error");
    });
    

    【讨论】:

    • 仅适用于 jquery 2.x,不适用于 1.x
    【解决方案7】:

    我用它来捕获 JSON 错误

    try {
       $.getJSON(ajaxURL,callback).ajaxError();
    } catch(err) {
       alert("wow");
       alert("Error : "+ err);
    }
    

    编辑: 或者,您也可以收到错误消息。这会让你知道错误到底是什么。在 catch 块中尝试以下语法

    alert("Error : " + err);
    

    【讨论】:

    • 如何对异步调用执行 try/catch?就 try/catch 而言,调用立即结束。回调或任何错误将在我们离开此代码的范围后很久之后发生
    【解决方案8】:

    也许这行得通?

    .complete(function(response, status) {
        if (response.status == "404")
            alert("404 Error");
        else{
            //Do something
        }   
        if(status == "error")
            alert("Error");
        else{
            //Do something
        }
    });
    

    我不知道状态何时进入“错误”模式。但我用 404 对其进行了测试,它响应了

    【讨论】:

    • 我们甚至可以检查错误函数的响应状态。更好的是我们可以利用误差函数。
    【解决方案9】:

    您可以通过在 ajax 请求中添加此属性来显式处理任何错误号:

    statusCode: {
            404: function() {
              alert("page not found");
            }
        }
    

    所以,你的代码应该是这样的:

    jQuery.ajax({
    type: "GET",
    statusCode: {
            404: function() {
              alert("page not found");
            }
    },
    url: handlerURL,
    dataType: "jsonp",
    success: function(results){
        alert("Success!");
    },
    error: function(XMLHttpRequest, textStatus, errorThrown){
        alert("Error");
    }
    });
    

    希望这对你有帮助:)

    【讨论】:

      【解决方案10】:

      我也在stackoverflow - Error handling in getJSON calls发布了这个答案

      我知道已经有一段时间没有人在这里回答了,发帖人可能已经从这里或其他地方得到了他的回答。然而,我确实认为这篇文章将帮助任何人在执行 getJSON 请求时寻找一种方法来跟踪错误和超时。因此,下面是我对问题的回答

      getJSON 结构如下(见http://api.jqueri.com):

      $(selector).getJSON(url,data,success(data,status,xhr))
      

      大多数人使用

      $.getJSON(url, datatosend, function(data){
          //do something with the data
      });
      

      他们使用 url var 提供指向 JSON 数据的链接,datatosend 作为添加 "?callback=?" 和必须发送的其他变量以获取返回的正确 JSON 数据的位置,成功函数为处理数据的函数。

      但是,您可以在成功函数中添加状态和 xhr 变量。 status 变量包含以下字符串之一:“success”、“notmodified”、“error”、“timeout”或“parsererror”,xhr 变量包含返回的 XMLHttpRequest 对象 (found on w3schools)

      $.getJSON(url, datatosend, function(data, status, xhr){
          if (status == "success"){
              //do something with the data
          }else if (status == "timeout"){
              alert("Something is wrong with the connection");
          }else if (status == "error" || status == "parsererror" ){
              alert("An error occured");
          }else{
              alert("datatosend did not change");
          }         
      });
      

      通过这种方式,可以轻松跟踪超时和错误,而无需实现在请求完成后启动的自定义超时跟踪器。

      希望这对仍在寻找这个问题的答案的人有所帮助。

      【讨论】:

      • 对不起,这对 jQuery 2.2.3 没有任何影响。
      猜你喜欢
      • 2011-12-10
      • 2013-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-03
      相关资源
      最近更新 更多