Safari双重提交ajax调用
我注意到Safari 5.0.5(6533.21.1)似乎在提交重复的ajax调用。当我运行下面的减少测试用例:Safari双重提交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"
这种行为似乎并没有在第一次请求发生,但所有后续REQ uests一式两份发送。有谁知道发生了什么事?努力检测js中的额外请求是徒劳的。
添加连接:关闭头API响应解决该问题。
你能解释一下吗?你在哪里添加了这段代码? – 2013-10-16 20:02:27
减少投票,因为这个答案是不完整的。请分享更多细节!此外,看起来像这可能是不安全的,根据这个:[http://stackoverflow.com/questions/2954958/modifying-jquery-ajax-request-connection-header](http://stackoverflow.com/questions/2954958 /修改-jQuery的AJAX请求连接头) – user3396385 2015-11-19 19:33:11
我认为浏览器对第二个呼叫作出conditional GET request(另见304 response status)。
第一次调用没有在浏览器中没有的缓存响应,它确实是这样一个正常的请求。
第二个请求中,浏览器首先执行一个条件GET请求,并且在看到它的缓存响应已过期时,它必须重复GET请求。
据我所知,jQuery有一个内置的修复(它会自动附加一个参数到请求url,类似_=123456789
)。我不知道为什么这不起作用。
你可以尝试用手工追加请求PARAM这样的:'/api/private/customers.json?v='+(new Date().getTime())
或者你可以尝试使用jQuery.ajax
与cache:false
,并dataType:'jsonp'
您可以打开Safari浏览器的开发者工具(Web检查),并检查网络选项卡。它会告诉你更多关于请求和响应的信息。
我不完全确定Safari有Network标签,因为我没有使用它。但Chrome的确如此,它们都是基于WebKit的,并且在这个角度上应该是相似的...... – 2011-05-10 21:46:46
谢谢。我尝试了这些选项,并进行了检查以确保过期头文件被设置为过期(他们是)。有趣的是,_参数对于重复请求是相同的(例如两个_ = 1305064165485值)。 – user747594 2011-05-10 21:52:03
预计最后两个请求具有相同的网址。 jQuery只生成两个请求(每个请求都有不同的_ = timestamp值)。但是对于第二个jQuery请求,浏览器进行干预,并且调用2个调用(一个cond.get和一个真正的GET)。这对javascript方面是透明的(它看起来只是一个请求)。这个_技巧应该是让这两个url不同,并诱使浏览器认为jQuery创建的两个请求是不同的。显然,Safari忽略了请求参数,并且只比较了基本url ... – 2011-05-10 22:02:53
我想我们不会知道它是一个错误还是一个功能......无论如何,Safari(如10.0.2版本)仍然执行conditionnal request,正如Dan Manastireanu所解释的那样。 我发现请求不重复的方式是使用当前请求时间设置一个'If-Unmodified-Since'
标头。 (或者,您也可以在URL添加时间戳参数,如Dan Manastireanu再次mentionned)
我downvoted的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);
}
你能添加下一个4秒请求?我想知道,如果第一个是第一个超时之后的第一个是2秒,然后它看起来像是显示“重复”,因为它是第一个超时更新的另一个2秒,第二个超时开始后的另一个4秒。这可能会导致它看起来像重复。 – 2011-05-10 21:15:57
谢谢布莱斯。对不起,如果这个例子造成混乱。我使用超时消除了重复点击事件的可能性。他们绝对是重复的。 – user747594 2011-05-10 22:07:02
我也有这个问题。 – 2013-10-16 20:00:06