12

I do lots of $.ajax calls, and I handle errors from them in a way that throws up a message. I find that if an ajax call is in progress while the page gets reloaded, e.g. click refresh, or navigate to another URL, then my in-progress ajax calls trigger their error callbacks.

How can I tell the difference between a real error, and a call that aborted because the page got reloaded?

$.ajax(...)
.success(...)
.error(function(jqXHR) {
  // jqXHR.status == 0 means either failed to contact server,
  // or aborted due to page reload -- how can I tell the difference?
});
kdt
  • 27,905
  • 33
  • 92
  • 139

3 Answers3

12

Add an unload handler, which sets a flag to true. Then, inside the error handler, you can check this flag, and do something appropriate.

Example:

var unloading = false;
$.ajax(...) ...
 .error(function(jqXHR) {
    if (unloading) return; // Ignore errors caused by navigating away
    // Now, check for real errors ..
});
$(window).unload(function() {unloading = true;});
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • 3
    this approach worked for me, but I had to put the error handler body inside of a `setTimeout(function(), 250)` because the error handler was firing before the window.unload() function – scootklein May 11 '13 at 16:10
2

The better way without timeouts and other magic flags is to check xhr headers. If no headers, then response didn't come from server, then request was aborted.

var isUserAbortedRequest = function (xhr) {
    return !xhr.getAllResponseHeaders();
}

ajaxRequest
    .fail(function (xhr, error, statusText) {
        console.log("request aborted = ", isUserAbortedRequest(xhr));
    })
    .success(...)

You can wrap your ajax request with $.Defered like below and use defered object's done\fail.

$.Deferred(function (def) {           
    ajaxRequest
        .fail(function (xhr, error, statusText) {
            console.log("request aborted = ", isUserAbortedRequest(xhr));

            def.reject({ aborted: isUserAbortedRequest(xhr), error: error });
        })
        .success(function (response) {
            if (response.success == true) {
                def.resolve(response.data);
            }
            else {
                def.reject({ aborted: false, error: response.error });
            }
        });
});
Madman
  • 3,171
  • 2
  • 32
  • 44
  • These seems preferable compared to the other answers. Relevant, related Q&A: http://stackoverflow.com/questions/9229005/how-to-handle-jquery-ajax-post-error-when-navigating-away-from-a-page – Luke Jul 29 '16 at 21:32
  • This solution only distinguishes between errors that come from the server and errors that do not. But it cannot distinguish between a network error (which does not come from the server) and a user moving away from the page. – Benedikt Nov 27 '20 at 11:04
1
var unloading = false;
$.ajax(...) ...
 .error(function(jqXHR) {
    if (unloading) return; // Ignore errors caused by navigating away
    // Now, check for real errors ..
});
$(window).unload(function() {unloading = true;});

The above technique 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.

Sachindra
  • 2,052
  • 4
  • 23
  • 29