介绍
这个问题似乎比实际更长,但我试图保持一个干净的结构.
首先,我有这个webapp,它需要在文件大小非常小,以便能够在智能手机上完全加载(没有缓存)< 10秒.这要求我不要使用像jQuery这样的库(无论如何都没关系,见下文). 没有jQuery 我基本上使用MDN Ajax page来创建这个短包装器:
function ajax(options) {
var request;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else {
request = new ActiveXObject("Microsoft.XMLHTTP");
}
request.timeout = 6500;
request.ontimeout = function () {
// not called, 6.5s is too high for a timeout anyway, checked this one first
options.error(request);
};
request.onreadystatechange = function () {
if (request.readyState == 4) {
if (request.status >= 200 && request.status < 400) {
options.success(request.responseText);
} else {
options.error(request);
}
}
};
request.open("GET", options.url, true);
request.send();
}
但是,有时(在1/15到1/100的情况下)请求失败.我得到一个类似于这个的请求对象:
XMLHttpRequest {
onreadystatechange: ajax/request.onreadystatechange(),
readyState: 4,
timeout: 6500,
withCredentials: false,
upload: XMLHttpRequestUpload,
responseURL: "my-url",
status: 0, // <-- this seems to be the main problem
statusText: "",
responseType: "",
response: ""
}
要说明这一点,我不是想在这里做CORS,它都在同一个域上.此外,超时设置为6.5秒,如果我查看其他请求,它们通常在~45ms内完成.我尝试“重试”Ajax 3x,如果它失败一次,赶上“status = 0” – 问题,但是这并不总是有效,因为它仍然发生,0表示网络服务器没有提供任何内容(这种解决方法似乎是一个非常脏的黑客).
使用jQuery Ajax
在另一个项目我使用jQuery因为我没有这些大小限制.我正在使用常规的jQuery.ajax调用,就像这样:
$.ajax({
url: url,
dataType: "json",
success: options.updateSuccess,
error: options.updateError,
timeout: options.updateTimeout
});
然而,即使这个有时也失败,statusCode = 0(updateTimeout设置为65s,因为我“可以等待这个”).它也是一个与第一个片段不同的网络服务器.
到目前为止我尝试了什么?
>做一些研究(事实证明很多人都想使用我不想做的CORS)
>通过在网址上附加时间戳来防止浏览器使用网站的缓存版本(“& cache =”new Date().getTime(),也不起作用)
>检查Web服务器是否有错误的配置(这不是这个问题的根源,我甚至尝试使用简短的Python脚本在Ajax调用的相同时间间隔内查询站点,它们都成功了)
>尝试了不同的浏览器:这主要发生在Firefox中,虽然Chrome似乎偶尔会失败
最后的问题
为什么会这样呢?我不能反复复制它,它有时会发生.这是一个浏览器错误,使每个第n个Ajax调用失败吗?你有什么不同的方法来解决这个问题(最好用普通的Javascript)吗?
更新
我做了一些更多的研究,这次是使用wireshark.我记录了哪个请求导致status = 0,然后查看了这些包的TCP流程图,所有请求都得到了服务器的答案,我想这不是服务器端问题.
解决方法:
所以我通过做了很多测试来解决这两个问题. jQuery一个很简单,更新到jQuery 2.1.4解决了它,我不想知道是什么导致了这个,它现在才起作用.
对于第二个问题,我将超时减少到500毫秒,然后遇到超时,这导致我的onreadystate被调用,即使请求没有完成(在获得时间的答案方面)完全因此获得状态= 0为什么这之前发生过,见上文.为了确保超时不仅仅是“随机”,我添加了一个重试计数器并修改了我的Ajax函数:
function ajax(options) {
var request;
if (options.retry === undefined) {
options.retry = 3; // modify here for default retry count
}
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else {
request = new ActiveXObject("Microsoft.XMLHTTP");
}
request.timeout = options.timeout ? options.timeout : 500; // modify here for default timeout
request.ontimeout = function () {
if (options.retry > 0) {
options.retry--;
ajax(options);
} else {
options.error(request);
}
};
request.onreadystatechange = function () {
var delta = new Date().getTime() - request.startTime;
if (request.readyState == 4) {
if (request.status >= 200 && request.status < 400) {
options.success(request.responseText);
} else if (request.status === 0 && delta >= request.timeout) {
// do nothing as this was "just a timeout"
} else {
options.error(request);
}
}
};
request.startTime = new Date().getTime();
request.open("GET", options.url, true);
request.send();
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。