jQuery ajax(jsonp)忽略超时并且不会触发错误事件

Mat*_*ijs 89 ajax error-handling jquery jsonp timeout

为了添加一些基本的错误处理,我想重写一段使用jQuery的$ .getJSON来从Flickr中提取一些照片的代码.这样做的原因是$ .getJSON不提供错误处理或使用超时.

因为$ .getJSON只是$ .ajax的包装,所以我决定改写这个东西并惊喜,它完美无缺.

现在开始有趣了.当我故意导致404(通过更改URL)或导致网络超时(没有连接到互联网)时,错误事件根本不会触发.我不知道自己做错了什么.非常感谢帮助.

这是代码:

$(document).ready(function(){

    // var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne"; // correct URL
    var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne_______"; // this should throw a 404

    $.ajax({
        url: jsonFeed,
        data: { "lang" : "en-us",
                "format" : "json",
                "tags" : "sunset"
        },
        dataType: "jsonp",
        jsonp: "jsoncallback",
        timeout: 5000,
        success: function(data, status){
            $.each(data.items, function(i,item){
                $("<img>").attr("src", (item.media.m).replace("_m.","_s."))
                          .attr("alt", item.title)
                          .appendTo("ul#flickr")
                          .wrap("<li><a href=\"" + item.link + "\"></a></li>");
                if (i == 9) return false;
            });
        },
        error: function(XHR, textStatus, errorThrown){
            alert("ERREUR: " + textStatus);
            alert("ERREUR: " + errorThrown);
        }
    });

});
Run Code Online (Sandbox Code Playgroud)

我想补充说,当jQuery版本为1.4.2时,会问这个问题

Hus*_*sky 86

jQuery 1.5及更高版本可以更好地支持JSONP请求的错误处理.但是,您需要使用该$.ajax方法而不是$.getJSON.对我来说,这有效:

var req = $.ajax({
    url : url,
    dataType : "jsonp",
    timeout : 10000
});

req.success(function() {
    console.log('Yes! Success!');
});

req.error(function() {
    console.log('Oh noes!');
});
Run Code Online (Sandbox Code Playgroud)

超时似乎可以解决问题并在10秒后没有成功请求时调用错误处理程序.

我也在这个主题上做了一些博文.

  • 我现在已经非常生气了,因为我已经对这个问题进行了2天的攻击,并且需要在StackOverflow上进行一些模糊的搜索才能发现我必须在跨域请求中添加超时以触发错误.如何在jQuery文档中不提及它?跨域jsonp请求真的不常见吗?无论如何,谢谢,谢谢,谢谢.+1 (23认同)
  • @Tarlog:这是合乎逻辑的.JSONP请求不是本机Ajax请求,它们只是动态插入的Javascript"<script>"标记.因此,您唯一可以知道的是请求失败,而不是状态代码.如果要获取状态代码,则需要使用传统的Ajax请求或其他跨域技术. (10认同)

Jos*_*lio 67

这是jQuery中本机jsonp实现的已知限制.以下文本来自IBM DeveloperWorks

JSONP是一种用于构建mashup的非常强大的技术,但不幸的是,它并不能解决所有跨域通信需求.它有一些缺点,在提交开发资源之前必须认真考虑.首先,JSONP调用没有错误处理.如果动态脚本插入有效,则会调用; 如果没有,没有任何反应.它只是默默地失败了.例如,您无法从服务器捕获404错误.你也不能取消或重启请求.但是,等待一段合理的时间后,您可以超时.(未来的jQuery版本可能具有JSONP请求的中止功能.)

但是,GoogleCode上提供了一个jsonp插件,可以为错误处理提供支持.要开始使用,只需对代码进行以下更改即可.

您可以下载它,也可以只向插件添加脚本引用.

<script type="text/javascript" 
     src="http://jquery-jsonp.googlecode.com/files/jquery.jsonp-1.0.4.min.js">
</script>
Run Code Online (Sandbox Code Playgroud)

然后修改你的ajax调用,如下所示:

$(function(){
    //var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne"; // correct URL
    var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne_______"; // this should throw a 404  
    $.jsonp({
        url: jsonFeed,
        data: { "lang" : "en-us",
                "format" : "json",
                "tags" : "sunset"
        },
        dataType: "jsonp",
        callbackParameter: "jsoncallback",
        timeout: 5000,
        success: function(data, status){
            $.each(data.items, function(i,item){
                $("<img>").attr("src", (item.media.m).replace("_m.","_s."))
                          .attr("alt", item.title)
                          .appendTo("ul#flickr")
                          .wrap("<li><a href=\"" + item.link + "\"></a></li>");
                if (i == 9) return false;
            });
        },
        error: function(XHR, textStatus, errorThrown){
            alert("ERREUR: " + textStatus);
            alert("ERREUR: " + errorThrown);
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

  • 另一位开发人员通过此提示保存 谢谢! (7认同)

Bet*_*ida 12

一个解决方案,如果你坚持使用jQuery 1.4:

var timeout = 10000;
var id = setTimeout( errorCallback, timeout );
$.ajax({
    dataType: 'jsonp',
    success: function() {
        clearTimeout(id);
        ...
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 只是一个评论,它是一个有效的解决方案,坚持1.4,但设置你的超时变量足够高,所以你没有慢的webservices问题:).例如,如果你把它设置为一秒钟,你可以看到我的意思,错误回调被触发,而在那之后1秒你的呼叫仍然被获取并调用成功函数.所以请记住将它设置得足够高 (2认同)

小智 8

这可能是jQuery的"已知"限制; 但是,它似乎没有很好的记录.今天我花了大约4个小时试图理解为什么我的超时不起作用.

我切换到jquery.jsonp,它的工作很喜欢魅力.谢谢.