Safari双重提交ajax调用

时间:2011-05-10 21:09:14

标签: javascript jquery ajax safari

我注意到Safari 5.0.5(6533.21.1)似乎正在提交重复的ajax调用。当我运行以下简化测试用例时:

// jquery 1.6 include
$(document).ready(function() {
    setTimeout(function(e) {
        var req1 = $.getJSON('/api/private/customers.json');
        console.log('req1 sent');
    }, 2000);
    setTimeout(function(e) {
        var req2 = $.getJSON('/api/private/customers.json');
        console.log('req1 sent');
    }, 4000);
});

Safari资源面板和控制台显示两个xhr请求,但我的服务器日志显示三个xhr请求:

XX.XX.XX.XXX - - [10/May/2011:16:50:40 -0400] "GET /api/private/customers.json HTTP/1.1" 200 183 "https://sub.mydomain.com/customers" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-us) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1"
XX.XX.XX.XXX - - [10/May/2011:16:50:42 -0400] "GET /api/private/customers.json HTTP/1.1" 200 183 "https://sub.mydomain.com/customers" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-us) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1"
XX.XX.XX.XXX - - [10/May/2011:16:50:42 -0400] "GET /api/private/customers.json HTTP/1.1" 200 183 "https://sub.mycomain.com/customers" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-us) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1"

当我使用最新版本的Firefox发出相同的请求时,我正确地收到了两个请求:

XX.XX.XX.XXX - - [10/May/2011:16:52:00 -0400] "GET /api/private/customers.json HTTP/1.1" 200 183 "https://sub.mycomain.com/customers" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"
XX.XX.XX.XXX - - [10/May/2011:16:52:02 -0400] "GET /api/private/customers.json HTTP/1.1" 200 183 "https://sub.mycomain.com/customers" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"

第一个请求似乎没有发生此行为,但所有后续请求都是一式两份发送的。有谁知道发生了什么事?在js中检测额外请求的努力是徒劳的。

3 个答案:

答案 0 :(得分:3)

我想我们不会知道这是一个错误还是一个功能......无论如何,Safari(在10.0.2版本中)仍然按照conditionnal request的说明执行Dan Manastireanu。 我发现请求不重复的方法是使用当前请求时间设置'If-Unmodified-Since'标头。 (或者您也可以在网址中添加时间戳参数,Dan Manastireanu再次提及)

我对setRequestHeader('Connection', "close")进行了投票,因为它是forbidden header name并抛出Refused to set unsafe header "Connection"错误。

所以基本请求如下:

var get = function(url, callbackSucess, callbackError) {
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.timeout = 10000;

    var now = new Date().getTime();
    request.setRequestHeader('If-Unmodified-Since', now);

    request.onreadystatechange = function() {
        if (request.readyState !== 4) {
            return;
        }
        if (request.status === 200) {
            callbackSucess(request.status);
        } else {
            callbackError(request.status);
        }
    };
    request.onerror = function (error) {
        callbackError(error);
    };
    request.ontimeout = function () {
        request.abort();
    };
    request.send(null);
}

答案 1 :(得分:2)

我认为浏览器正在为第二个电话拨打conditional GET request(另请参阅304 response status)。

在第一次调用时,浏览器中没有缓存响应,因此它会执行正常请求 在第二个请求中,浏览器首先执行条件GET请求,并且在看到其缓存的响应已过期时,它必须重复GET请求。

据我所知,jQuery有一个内置的修复程序(它自动将一个参数附加到请求URL,类似_=123456789)。我不知道为什么这不起作用。

您可以尝试手动附加请求参数:'/api/private/customers.json?v='+(new Date().getTime())
或者您可以尝试将jQuery.ajaxcache:falsedataType:'jsonp'

一起使用

您可以打开Safari的开发人员工具(Web Inspector),然后查看“网络”选项卡。它会告诉您有关请求和响应的更多信息。

答案 2 :(得分:1)

在API响应中添加连接:关闭标头可以解决问题。