Introduction
This question seems longer than it actually is, but I tried to keep a clean structure.
To start off, I have this webapp which needs to be very small in filesize to be able to load completely (without cache) on your smartphone in < 10s. This requires me to not use a library like jQuery (which doesn't matter anyway, see below).
Without jQuery
I basically used the MDN Ajax page to create this short wrapper:
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();
}
However, sometimes (in like 1/15 up to to 1/100 cases) the request fails. I get a request object similar to this one:
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: ""
}
To point this out, I'm not trying to do CORS here, it's all on the same domain. Also the timeout is set to 6.5s, if I look at the other requests, they usually complete within ~45ms. I tried to "retry" the Ajax 3x if it fails once, to catch the "status = 0"-problem, however this didn't always work out yet as it still occured and 0 means the webserver didn't deliver any content (this workaround just seems like a really dirty hack).
With jQuery Ajax
On another project I'm using jQuery because I don't have these size limits. I'm using a regular jQuery.ajax call, just like this:
$.ajax({
url: url,
dataType: "json",
success: options.updateSuccess,
error: options.updateError,
timeout: options.updateTimeout
});
However even this one sometimes fails with statusCode = 0 (the updateTimeout
is set to 65s as I "can wait for this one"). Also it's a different webserver than in the first snippet.
What have I tried so far?
- do some research (turns out many people wanted to use CORS which I'm not trying to do)
- preventing the browser to use a cached version of the site by appending a timestamp to the url (
"&cache=" + new Date().getTime()
, didn't work too) - check the webserver for wrong configuration (it wasn't the source of this problem, I even tried polling the site with a short Python script in the same intervals like the Ajax calls and they all succeeded)
- tried different browsers: this mainly happens in Firefox, although Chrome also seems to fail once in a while
Final Question
Why does this happen then? I'm not capable of reproducing it repeatedly, it just sometimes happens. Is this a browser bug that makes every n-th Ajax call fail? Do you have any different approaches to solve this (preferably with plain Javascript)?
Update
I did some more research, this time with wireshark. I logged which request caused the status = 0
and then viewed the TCP flow graph of these packages and all requests got an answer from the server, I guess it's not a server side problem.