Friday, December 11, 2009

How to Distinguish a User-Aborted AJAX Call from an Error

Copied from: How to Distinguish a User-Aborted AJAX Call from an Error .


Let’s say you’re writing a LOLcats app and you want to be all user-friendly and show an adorable little kitty-cat error message whenever an AJAX call fails. So you write an error handler using your favorite cross-browser library (mine is jQuery), something like this:
1$.ajax( { url: "someUrl", success: function() {
2  // do something impressive with the results
3}, error: function() {
4  showError("Ohs noes. Tell me when you fix your AJAX.");
5} } );
But you start using your app and you notice that your error message also appears when you navigate away from the page before an AJAX call has finished, or when you hit Escape to cancel the AJAX call. That kind of sucks—it looks ugly to have the error message appear when there really was no error.
I did a little looking around and found what looks like a cross-browser-friendly way to tell if an error really occurred or if something else happened, like the user navigating away or hitting Escape.
The trick is to check the response headers in the XMLHttpRequest object. If there are no response headers (null or empty string, depending on the browser), the server did not respond yet. That means the user aborted.
Here’s a function that takes an XMLHttpRequest and tells you if the user aborted it.
01/**
02 * Returns true if the user hit Esc or navigated away from the
03 * current page before an AJAX call was done. (The response
04 * headers will be null or empty, depending on the browser.)
05 *
06 * NOTE: this function is only meaningful when called from
07 * inside an AJAX "error" callback!
08 *
09 * The 'xhr' param is an XMLHttpRequest instance.
10 */
11function userAborted(xhr) {
12  return !xhr.getAllResponseHeaders();
13}
And here is the updated application code to call this new function. You can easily adapt this to another JavaScript library than jQuery:
1$.ajax( { url: "someUrl", success: function() {
2  // do something impressive with the results
3}, error: function(xhr, textStatus, errorThrown) {
4  if (!userAborted(xhr)) {
5    showError("Ohs noes. Tell me when you fix your AJAX.");
6  }
7} } );
Oh, did that “textStatus” and “errorThrown” catch your eye? I already looked at those. You can’t use them to tell if the user aborted. They return the same values whether the user aborted or the server returned with an error. (I only tested a 500 error.)

1 comment: