jQuery AJAX fires error callback on window unload - how do I filter out unload and only catch real errors?

In the error callback or $.ajax you have three input arguments:

function (XMLHttpRequest, textStatus, errorThrown) {
   this; // options for this ajax request
}

You can check directly the xhr.status to get the HTTP response code, for example:

$.ajax({
  url: "test.html",
  cache: false,
  success: function(html){
    $("#results").append(html);
  },
  error: function (xhr, textStatus) {
    if (xhr.status == 500) {
      alert('Server error: '+ textStatus);
    }
  }
});

Edit: To tell the difference between a connection broken by the browser and the case where the server is down (jasonmerino's comment):

On unload the xhr.readyState should be 0, where for a non responsive server the xhr.readyState should be 4.


This is a tough one to handle correctly in all situations. Unfortunately in many popular browsers the xhr.status is the same (0) if the AJAX call is cancelled by navigation or by a server being down / unresponsive. So that technique rarely works.

Here's a set of highly "practical" hacks that I've accumulated that work fairly well in the majority of circumstances, but still isn't bullet-proof. The idea is to try to catch the navigate events and set a flag which is checked in the AJAX error handler. Like this:

var global_is_navigating = false;

$(window).on('beforeunload',function() {
    // Note: this event doesn't fire in mobile safari
    global_is_navigating = true;
});

$("a").on('click',function() {
    // Giant hack that can be helpful with mobile safari
    if( $(this).attr('href') ) {
        global_is_navigating = true;
    }
});

$(document).ajaxError(function(evt, xhr, settings) {
    // default AJAX error handler for page
    if( global_is_navigating ) {
        // AJAX call cancelled by navigation. Not a real error
        return;
    }
    // process actual AJAX error here.
});

(I'd add this as a comment to the main answer but haven't built up enough points to do so yet!)

I'm also seeing this in FF4 and Chrome (9.0.597.107). Probably elsewhere but that's bad enough for me to want to fix it!

One of the things that's odd about this situation is that returned XMLHttpRequest.status === 0

Which seems like a reliable way to detect this situation and, in my particular case, abort the custom error handling that displays to the user:

error: function (XMLHttpRequest, textStatus, errorThrown) {
    if (XMLHttpRequest.status === 0) return;
    // error handling here
}

Also worth mentioning that on the assumption if may be a problem in the JSON parse of whatever the browser is giving back to the $.ajax() call, I also tried swapping out the native JSON.stringify for the Douglas Crockford version ( https://github.com/douglascrockford/JSON-js ) but that made no difference.