i apologise if this is something i should be able to look up. all of the terms i wanted were way overloaded..
here is my problem: when i open a page, it fires off a whole series of ajax calls. if i then press Shift+Refresh, all of those ajax calls are being considered errors, and showing their error message dialogs before the entire page itself reloads.
so the error is being triggered by the client - is there anyway i can find out if this is the case so i can ignore it? eg in the xmlhttprequest, or in the ajax function (i am using jquery btw)
[this is an edit from the previous answer, which had outstanding questions that I have since resolved]
jQuery throws the error event when the user navigates away from the page either by refreshing, clicking a link, or changing the URL in the browser. You can detect these types of errors by by implementing an error handler for the ajax call, and inspecting the xmlHttpRequest object:
$.ajax({
/* ajax options omitted */
error: function (xmlHttpRequest, textStatus, errorThrown) {
if(xmlHttpRequest.readyState == 0 || xmlHttpRequest.status == 0)
return; // it's not really an error
else
// Do normal error handling
});
There are several suggested approaches for detecting this:
Several have suggested the use of a beforeunload
handler to set a boolean flag so that the error handler can know that the page is being unloaded (See list of related/duplicated posts below). This is great, except that mobile Safari on iOS doesn't support the beforeunload
event.
Sachindra suggested an approach where instead of firing the error function immediately, it got delayed a second in a setTimeout(..., 1000)
. That way, there is a good chance the page has actually disappeared by the time the error handler gets called. "Good chance" that is. I bet if I have a huge page with e.g. many <input>
s, it could take more than 1 sec to unload, and then perhaps the error handler would fire anyway.
I therefore suggest a combination of reliably detecting beforeunload
support and if beforeunload
is not supported (cough iPad/iPhone cough) revert to Sachindra's delay trick.
See the full solution with beforeunload
detection and all in this jsfiddle.
It looks like the situation is a little better for jQuery 2.x than for 1.x, but 2.x also seems a little flakey, and so I still find this suggestion prudent.
P.S: There were also suggestions involving testing some fields in the XHR
/ jqXHR
object. (Here and here). I have not come accross a combination that could distinguish between user navigation and restarting the webserver during a long-running AJAX call, and I have therefore not found this approach useful to me.
This is really also an answer to these related/duplicated Stack Overflow questions:
- jQuery AJAX fires error callback on window unload?
- $.ajax calls success handler when request fails because of browser reloading
- How best to handle errors during jquery ajax calls caused by user clicking on links
- Detecting that a jQuery.ajax call failed because the page is reloading?
and these posts outside of Stack Overflow:
- What's the proper way to deal with AJAX error because of page reload?
- How to Distinguish a User-Aborted AJAX Call from an Error | I like stuff.
var isPageBeingRefreshed = false;
window.onbeforeunload = function() {
isPageBeingRefreshed = true;
};
$.ajax({
error: function (xhr, type, errorThrown) {
if (!xhr.getAllResponseHeaders()) {
xhr.abort();
if (isPageBeingRefreshed) {
return; // not an error
}
}
}
});
The above techniques does not work for a periodically refreshing page (for example every half seconds). I have figured out that the error caused by refreshing the page can be avoided using delaying the error handling process by a small amount of time.
Example:
$.ajax(...)
.success(...)
.error(function(jqXHR) {
setTimeout(function() {
// error showing process
}, 1000);
});
In addition to that
window.onbeforeunload = function() {//stop ajax calls}
event can be used for less frequently refreshing ajax calls.
Combined version of nisanth074 and Peter V. Mørch answers, that worked for me.
Example:
var isPageBeingRefreshed = false;
$(window).on('beforeunload', function(){
isPageBeingRefreshed = true;
});
$.ajax({
// Standart AJAX settings
}).error(function(){
if (!isPageBeingRefreshed) {
// Displaying error message
}
});