Yahoo! UI Connection Manager Response Controller

The Yahoo! UI connection manager is a great Ajax library. The library allows you to define a callback object that sends successful responses to one function and failures to another function. In this entry I propose finer control for more than just success of failure. Handlers for particular response status codes and a catch-all for complete. Also before and after filter handlers that allow for certain actions to take place for all responses regardless of the response status code.

Using the patch provided you can have a callback object like

var callback ={
  before: beforeFilter,
  on205: thisFunction,
  on514: thatFunction,
  failure: handleFailure,
  success: handleSuccess,
  after: afterFilter
}

Yahoo! UI connection manager v0.10

Based on the examples on the Yahoo! site, a typical example using the Yahoo! UI connection manager might look like the following

<script> 
  function handleSuccess(o){
    // do stuff
  }
  function handleFailure(o){
    // do stuff
  }
  var callback = { 
        success: handleSuccess, 
        failure: handleFailure
  };

    var transaction = YAHOO.util.Connect.asyncRequest('GET',
                         'http://www.example.com', callback); 
</script>

With the Yahoo! UI connection manager, responses with a header status code greater than or equal to 200 and less than 300 are sent to the handleSuccess function. All other responses are sent to handleFailure. This is great in situations where you only need two options to handle the response.

In one of my projects, I needed more options for handling handling the Ajax response. On the server, before I sent the response, I would set the status code in the response header. Below is a JavaScript code snip showing my method that allows very fine control and more flexibility for handling the Ajax response.

function window_replace(o){
  // do stuff
}

function multi_update(o){
  // do stuff
}

function error(o){
  // do stuff
}

function response_controller(o) {
  switch(o.status){
    case 200:
      window_replace(o);
      break;
    case 202:
      multi_update(o);
      break;
    default:
      error(o);
      break;
  }
}

var callback = { 
      success: response_controller, 
      failure: response_controller
};

var transaction = YAHOO.util.Connect.asyncRequest('GET',
                  'http://www.example.com', callback);

Because I send both success and failure responses to the same response_controller function, I can consider any response status codes to be a success even outside the [200,300) range. Similarly, response status codes in this range can be considered failures. They are all just responses that need to be handled. Alternatively, you could make two controllers: success_controller and failure_controller if you do not need the flexibility discussed in this paragraph.

By placing code inside response_controller before or after the switch statement you can run this code for any response.

I like the response_controller function as it parallels the controller classes in a Ruby on Rails application.

Prototype.js already does this

Prototype.js is a standard JavaScript library in any new Rails application. Prototype.js is not well liked by many. Read the archives on comp.lang.javascript for the reasons why. I don't particularly care for Prototype.js but the Ajax.request natively allows for more control of the response than the Yahoo! UI connection manager. With Ajax.request, it is possible to use onSuccess and onFailure handlers similar to my example above. Ajax.request also allows a courser onComplete which sends all, otherwise not handled, responses to a particular function.

Ajax.request also allows for finer control by allowing you to directly specify handler functions for specific response header status codes. They are defined with on304, on205, etc.

The JavaScript for an Ajax.request call might look like this example from the Script.aculo.us site

var opt = {
    method: 'post',
    postBody: 'thisvar=true&thatvar=Howdy&theothervar=2112',
    // Handle successful response
    onSuccess: function(t) {
        alert(t.responseText);
    },
    // Handle 404
    on404: function(t) {
        alert('Error 404: location "' + t.statusText + '" was not found.');
    },
    // Handle other errors
    onFailure: function(t) {
        alert('Error ' + t.status + ' -- ' + t.statusText);
    }
};

new Ajax.Request('/foo/bar', opt);

Suggested enhancement for Yahoo! UI connection mananger

The Ajax.request features are enough to offset the disadvantages of using Prototype.js but they are interesting. The Yahoo! UI connection manager is perfectly usable with the response_controller function; however, it would be nice to see the Ajax.request features in the Yahoo! UI connection manager.

If the Yahoo! UI connection manager allowed for the courser callback.complete property it would make my example above simpler. I could have a callback defined like the following

var callback = { 
      complete: response_controller
};

If the Yahoo! UI connection manager allowed for the callback.complete property and finer callback properties it would make my example above even simpler. I would not need response_controller function and could have a callback defined like the following

var callback = { 
  on200: window_replace,
  on202: multi_update,
  complete: error
};

Look how nice and tidy that would be!

Comments

Have something to write? Comment on this article.

Peter Michaux June 4, 2006

I have posted a patch for the connection manager that makes it possible to have a callback objects that can call functions based on the status code in the header

var callback ={
  on205: thisFunction,
  on514: thatFunction,
  failure: handleFailure,
  success: handleSuccess
}

or

var callback ={
  complete: handleAll
}

or

var callback ={
  on456: handle456,
  complete: handleOther
}

The connection manager will first look for an "onXXX" handler that matches the response status code XXX. If that doesn't exist it looks for success handler if the status code is in [200,300) or a failure handler if status code is outside this range. And finally a complete handler if were no other matches.

I think this works just like Prototype.js and I have tested it a bit. Seems to work fine.

You can use the

Patch for version 0.10

or you can use

Override functions for use with version 0.10

Enjoy:)

Peter Michaux June 6, 2006

I updated the patch and the override files so that you can have before and after filters that will run for all responses. This is good for response mangling or "loading" indicators.

function beforeFilter(o) {
 // mangle o and changes will
 // be propogate through regular handler
 // and afterFilter

 // do whatever you need to turn off
 // your loading indicator
}

function afterFilter(o) {
  // This could be a good place for
  // a setTimeout() call to make a 
  // periodic Ajax updater
}

var callback ={
  before: beforeFilter,
  on205: thisFunction,
  on514: thatFunction,
  failure: handleFailure,
  success: handleSuccess,
  after: afterFilter
}

Have something to write? Comment on this article.