Losing REST over Ajax Errors?

Andrew Krespanis

All too frequently, I see Ajax examples where the response is handled like this: (pseudo-code used for demonstration purposes)


xhr.onreadystatechange = function() 
{
  if ( xhr.readyState == 4 )
  {
    if (xhr.status == 200) 
    {
      // Process returned data (eg: Parse XML).
      
      // Check status of result depending on custom/ad-hoc error detection.
      //  -- most commonly a 0 for fail, or 1 for pass
      
      // Deal with/report error, or take some other action based upon returned data.
    }
  }
}

The above approach works, but as your application grows and your need to provide useful error reporting (and error avoidance!) increases, the good ol’ boolean-style error checking will quickly become unwieldy. I can see it now…

  1. Developer 1: What does an error code of 7 mean again?
  2. Developer 2: Ummm, Hang on, I’m sure we wrote that down somewhere…

Fear not, there’s a much smarter alternative, one which you rely upon every time you load up your browser—HTTP Status Codes (check out Mark Pilgrim’s humourous abridged list if the thought of reading yet another RFC sends you into an glazed-eyed stupor).

Taking the previous example, I’ve added a switch block for some of the status codes that will be most useful in handling the response to your JavaScript HTTP request:


xhr.onreadystatechange = function() 
{
  if ( xhr.readyState == 4 )
  {
    switch ( xhr.status )
    {
      case 200: // OK!
        /* 
         * If the request was to create a new resource 
         * (such as post an item to the database)
         * You could instead return a status code of '201 Created'
         */  
      break;
      
      case 304: // Not Modified
        /* 
         * This would be used when your Ajax widget is 
         * checking for updated content,
         * such as the Twitter interface.
         */   
      break;
      
      case 400: // Bad Request  
        /* 
         * A bit like a safety net for requests by your JS interface
         * that aren't supported on the server.
         * "Your browser made a request that the server cannot understand"
         */
      break;
      
      case 409: // Conflict 
        /* 
         * Perhaps your JavaScript request attempted to 
         * update a Database record 
         * but failed due to a conflict 
         * (eg: a field that must be unique)
         */
      break;
      
      case 503: // Service Unavailable
        /* 
         * A resource that this request relies upon
         * is currently unavailable 
         * (eg: a file is locked by another process)
         */
      break;    
    }
  }
}

So the next time you’re about to stick <status>1</status> or similar into an XML response, take a deeper look into HTTP Status Codes. It might be the first step towards getting some REST, which is most certainly a Good Thing™.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • chrisb

    so long as they remember what readystate 4 means..

  • tuna

    humm this is real old school programming method..just proves sometimes the old ways do have merit. :)

  • http://diigital.com cranial-bore

    Good idea. I was just thinking recently about the need for Javascript to be aware of both errors with the Ajax transactions, and errors on the server side as well.

  • pauldwaite

    Just in case people mentally blocked the “first step” bit, HTTP != REST.

  • http://basicstate.com/ plumsauce

    Since a lot of Ajax enthusiasts will land here, I’ll take this opportunity to post a suggestion:

    Avoid xmlhttp!

    Not that the component does not work, but because it throws a truly ugly error if the user has error messages enabled and activex disabled.

    So annoying!

  • Bryan Rasmussen

    I think I would use arrays for this, one for response codes, one for responses, if index out of range throw error, if response code not supported ignore response, choice as to whether to retry in bit or stop processing.