javascript xmlhttprequest 超时/中止没有按预期工作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8995085/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
xmlhttprequest timeout / abort not working as expected?
提问by Niet the Dark Absol
Here is my AJAX function:
这是我的 AJAX 函数:
/**
* Send an AJAX request
*
* @param url The URL to call (located in the /ajax/ directory)
* @param data The data to send (will be serialised with JSON)
* @param callback The function to call with the response text
* @param silent If true, doesn't show errors to the user
* @param loader The element containing "Loading... Please wait"
*/
AJAX = function(url,data,callback,silent,loader) {
var a,
attempt = 0,
rsc = function() {
if( a.readyState == 4) {
if( a.status != 200) {
if( a.status > 999) { // IE sometimes throws 12152
attempt++;
if( attempt < 5)
send();
else if( !silent) {
alert("HTTP Error "+a.status+" "+a.statusText+"<br />Failed to access "+url);
}
}
else if(!silent) {
alert("HTTP Error "+a.status+" "+a.statusText+"\nFailed to access "+url);
}
}
else {
callback(JSON.parse(a.responseText));
}
}
},
to = function() {
a.abort();
attempt++;
if( attempt < 5)
send();
else if( !silent) {
alert("Request Timeout\nFailed to access "+url);
}
};
data = JSON.stringify(data);
var send = function() {
if( loader && attempt != 0) {
loader.children[0].firstChild.nodeValue = "Error... retrying...";
loader.children[1].firstChild.nodeValue = "Attempt "+(attempt+1)+" of 5";
}
a = new XMLHttpRequest();
a.open("POST","/ajax/"+url,true);
a.onreadystatechange = rsc;
a.timeout = 5000;
a.ontimeout = to;
a.setRequestHeader("Content-Type","application/json");
a.send(data);
};
send();
};
The general idea is to attempt the request up to five times. Sometimes IE fails with an unusual HTTP error (12xxx), and sometimes the server may fail to respond.
一般的想法是尝试请求最多五次。有时 IE 会因异常的 HTTP 错误 (12xxx) 而失败,有时服务器可能无法响应。
The problem I'm having is that the abort()
call doesn't appear to be aborting the connection. To test, I made a simple PHP script:
我遇到的问题是abort()
呼叫似乎没有中止连接。为了测试,我制作了一个简单的 PHP 脚本:
<?php
sleep(60);
touch("test/".uniqid());
die("Request completed.");
?>
The touch()
call creates a file with the current uniqid()
- by looking at the modification time I can see the time the sleep(60)
ended.
该touch()
调用使用当前创建一个文件uniqid()
- 通过查看修改时间,我可以看到sleep(60)
结束的时间。
Expected behaviour:
预期行为:
The request is sent
After five seconds, the text changes to "Error... Retying... Attempt 2/5"
Repeat the above up until Attempt 5/5, then fail.
The five calls to the PHP file are aborted, and either there will be five files in the "test" folder, spaced 5 seconds apart, or there will be none because ignore_user_abort is off.
请求被发送
五秒后,文本变为“错误...重新输入...尝试 2/5”
重复上述直到尝试 5/5,然后失败。
对 PHP 文件的五个调用被中止,要么在“test”文件夹中有五个文件,间隔 5 秒,要么没有,因为 ignore_user_abort 关闭。
Observed behaviour (in IE9):
观察到的行为(在 IE9 中):
The request is sent
The attempt text appears and changes as it should
After five attempts, the error message is displayed
I am unable to load any pages for five whole minutes.
On the server, there are five files spaced one minute apart
请求已发送
尝试文本出现并按原样更改
五次尝试后,显示错误消息
我无法在整整五分钟内加载任何页面。
在服务器上,有五个文件间隔一分钟
I don't know what to make of this, because on the server side Requests 3, 4 and 5 are being sent minutes after the "Timeout" error message is shown on the browser.
我不知道该怎么做,因为在服务器端,请求 3、4 和 5 是在浏览器上显示“超时”错误消息几分钟后发送的。
If it makes any difference, the page making the AJAX calls is in an iframe. Reloading the iframe (using iframe.contentWindow.location.reload()
does NOT fix the issue, it still waits for those five requests to go through.
如果有任何区别,则进行 AJAX 调用的页面位于 iframe 中。重新加载 iframe(使用iframe.contentWindow.location.reload()
不能解决问题,它仍然等待这五个请求通过。
Why is this happening? How can I fix it?
为什么会这样?我该如何解决?
EDIT:I've run the test again using Developer Tools to monitor network activity. The result is:
编辑:我已经使用开发人员工具再次运行测试来监控网络活动。结果是:
URL Method Result Type Received Taken Initiator
/ajax/testto (Aborted) 0 B < 1 ms (Pending...)
/ajax/testto (Aborted) 0 B 125 ms (Pending...)
/ajax/testto (Aborted) 0 B 125 ms (Pending...)
/ajax/testto (Aborted) 0 B 125 ms (Pending...)
/ajax/testto (Aborted) 0 B 124 ms (Pending...)
采纳答案by Tango Bravo
When running your code, I got the error c00c023f. When I googled it, it came up with this answer:
运行您的代码时,我收到错误 c00c023f。当我用谷歌搜索它时,它想出了这个答案:
http://www.enkeladress.com/article.php/internetexplorer9jscripterror
http://www.enkeladress.com/article.php/internetexplorer9jscripterror
This sounds very similar to what you're experiencing.
这听起来与您正在经历的非常相似。
Here's a SO question which has the same problems, with a solution (also based on the above link, but with additional information): IE 9 Javascript error c00c023f
这是一个 SO 问题,它有同样的问题,有一个解决方案(也基于上面的链接,但有附加信息):IE 9 Javascript error c00c023f
回答by Jonathan Lonowski
The problem seems to be that timeout
and ontimeout
aren't yet part of some implementations:
问题似乎是,timeout
并且ontimeout
还不是某些实现的一部分:
var hasTimeout = 'timeout' in new XMLHttpRequest(); // false
At least, it's not in Chrome 16 or Firefox 7. And, this should return true
given the requirements:
至少,它不在 Chrome 16 或 Firefox 7 中。而且,true
根据要求,这应该返回:
The
timeout
attribute must return its value. Initially its value must be zero.
该
timeout
属性必须返回其值。最初它的值必须为零。
Both have been part of the XHR 2 specsince Sept 7, 2010. But, as the "Level 2" spec has been been around since Feb 25, 2008and is still a "Working Draft," there's not really a guarantee that any implementation would be up-to-date with the spec.
自2010年9 月 7 日以来,两者都已成为XHR 2 规范的一部分。但是,由于“Level 2”规范自2008年2 月 25 日起就已经存在并且仍然是“工作草案”,因此并不能真正保证任何实现都会与规范保持同步。
Without those available to you, you can try instead using onabort
and setTimeout
(as you stated in your comment):
如果没有这些可用,您可以尝试使用onabort
和setTimeout
(如您在评论中所述):
// snip
to = function() {
attempt++;
if( attempt < 5)
send();
else if( !silent) {
console.log("Request Timeout\nFailed to access "+url);
}
};
// snip
var send = function() {
if( loader && attempt != 0) {
loader.children[0].firstChild.nodeValue = "Error... retrying...";
loader.children[1].firstChild.nodeValue = "Attempt "+(attempt+1)+" of 5";
}
a = new XMLHttpRequest();
a.open("POST","/ajax/"+url,true);
a.onreadystatechange = rsc;
setTimeout(function () { /* vs. a.timeout */
if (a.readyState < 4) {
a.abort();
}
}, 5000);
a.onabort = to; /* vs. a.ontimeout */
a.setRequestHeader("Content-Type","application/json");
a.send(data);
console.log('HTTP Requesting: %s', url);
};
// snip
Example: http://jsfiddle.net/AmQGM/2/-- The ?delay=2
should finish, while the ?delay=10
expires its 5 tries.
示例:http: //jsfiddle.net/AmQGM/2/-?delay=2
应该完成,而?delay=10
过期则是 5 次尝试。
回答by dave
Before aborting the request, try setting
在中止请求之前,请尝试设置
a.onreadystatechange = function() {};
after that, also add a check around calling abort:
之后,还要添加一个关于调用 abort 的检查:
if( a.readyState > 0 && a.readyState < 4 ) {
a.abort();
}
回答by Sabo
I had the same problem, it turned out to be the issue with PHP session. If the session is open, all other requests from the same session must wait.
我遇到了同样的问题,结果是 PHP 会话的问题。如果会话处于打开状态,则来自同一会话的所有其他请求都必须等待。
<?php
session_write_close();
sleep(60);
touch("test/".uniqid());
die("Request completed.");
?>
This, of course, would not help you if you haven't started the session :)
当然,如果您还没有开始会话,这对您没有帮助:)