使用 JSONP 时如何捕获 jQuery $.getJSON(或数据类型设置为“jsonp”的 $.ajax)错误?

Posted

技术标签:

【中文标题】使用 JSONP 时如何捕获 jQuery $.getJSON(或数据类型设置为“jsonp”的 $.ajax)错误?【英文标题】:How do I catch jQuery $.getJSON (or $.ajax with datatype set to 'jsonp') error when using JSONP? 【发布时间】: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)。 【参考方案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。如果您无法捕获错误,您至少可以在等待一段合理的时间后超时。

【讨论】:

错误报告 #3442 链接已损坏。这可能是正确的链接:Ticket #3442 (closed enhancement: fixed) 同意!!!一个问题,即使我正在进行 JSONP 调用并收到 404 错误,但我没有收到 406 和 401 ???为什么 ??? ***.com/questions/18570486/… 错误答案,正确的是描述使用 .fail(function()) 的答案 这个答案不应该是正确的(现在?)***.com/a/19075701/2617354 是正确的方法。【参考方案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() 回调来检查是否发生了错误。

希望这会有所帮助:)

【讨论】:

请注意,这仅适用于版本 2.x(已放弃对 IE @LaurensRietveld 从 v1 开始支持:api.jquery.com/jQuery.getJSON【参考方案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 没有任何影响。

以上是关于使用 JSONP 时如何捕获 jQuery $.getJSON(或数据类型设置为“jsonp”的 $.ajax)错误?的主要内容,如果未能解决你的问题,请参考以下文章

在跨域请求中捕获 JSONP 错误

jsonp 请求中的“未捕获的类型错误:无法读取未定义的属性‘toLowerCase’”

WCF 跨域使用 Jsonp 错误未捕获语法错误:意外令牌:

使用带有 JSONP 的 AJAX 未捕获的 SyntaxError 和 CORS 错误

使用 jQuery 中止 JSONP ajax 请求

使用 jQuery 1.5 将请求作为 jsonp 发送,将响应解释为文本