JQuery_ Novice to Ninja - Earle Castledine [91]
// "this" now refers to the #result element
$(this).html(data);
}
});
Handling Errors
Error handling in Ajax is often left in the “we’ll do it at the end” basket. But it’s a basket that’s seldom emptied. There are a few reasons for this. One is that proper error handling can be tricky to implement. Another is that errors might appear to occur infrequently—especially when we’re developing on a local network. As a result, it can sometimes feel like time spent on developing error handling is wasted.
Nothing could be further from the truth! Errors happen—all the time. You know this is true, because you’ve seen hundreds of them, on web sites and in desktop applications. How your application recovers from problems is key to the overall impression your users will take away from your site.
One of the most common types of error that the end user will experience is when an Ajax interaction starts … but never ends. This will often be experienced as an eternally spinning, animated GIF. It’s a torturous position to be in: Is the page still working? Should I wait just a minute longer? Has my data really been submitted, and if I refresh will it send it all again? Sometimes this will be caused by a JavaScript error (usually when unexpected data is returned), but more often than not, it is because the developer failed to implement any timeout handling.
jQuery includes a simple method for handling timeouts—so there’s no excuse for leaving this step out. Like many of the Ajax options, you can specify both local and global level settings, so you can tailor your error handling to your application. To set a global timeout for all requests, use the $.ajaxSetup method and set the timeout property. Let’s set ours to 20 seconds:
$.ajaxSetup({
timeout: 20000
});
If you have some requests that you expect (or need) to come back faster, you can override the global timeout in the request itself:
$.ajax({
timeout: 4000,
…
});
It’s all well and good to see that your request has timed out—but what are you supposed to do about it? jQuery will give us a fairly good clue as to what went wrong. The error event fires whenever something goes wrong—and this includes when your timeout delay expires.
The handler we specify for this event will receive the XmlHTTPRequest object and a status message that we can use to determine the cause of the error; timeout, error (for HTTP errors, such as everyone’s favorite, 404), and parsererror (which would indicate improperly formatted XML or JSON) are values you might see.
You can choose to react differently to different errors, but typically you’ll want to simply try the request again. We’ll use the setTimeout function to wait for a second before sending another request (you might need to add some code to make your server sleep for the duration of the timeout, in order for an error to occur):
chapter_06/12_ajax_error_handling/script.js (excerpt)
var GALLERY = {
delay: 1000,
…
load: function() {
var _gallery = this;
$.ajax({
type:"get",
url: this.url,
…
error: function(xhr, status) {
setTimeout(function() {
_gallery.load();
}, _gallery.delay);
}
}
});
Any errors that arise from the load operation will fire the error code, which will call load again … over and over until it succeeds. Is that a good idea? Probably not! If it has failed ten times in a row, it would seem unlikely to suddenly work the eleventh time around, so at some point we’re going to have to throw up our hands and say, “That’s it!”
So to finesse this a little bit, we’ll make a couple of changes: first we’ll add a counter variable, which we’ll call attempts. Secondly, we’re going to be modifying the delay time on each request (we’ll see why soon), so we need to add a new method to reset everything to the initial values:
chapter_06/12_ajax_error_handling/script.js (excerpt)
var GALLERY = {
delay: 1000,
attempts: 3,
reset: function() {
this.delay = 1000;
this.attempts = 3;
},
…
}
The reset method will be called whenever a request successfully completes, or when we give up entirely because of too many errors.