The AjaxObject class is a layer built on top of the YUI Connection Utility to simplify dealing with the AJAX communication. It ensures the required connection parameters are set, simplifies client- and server-side error handling, provides automatic polling, prevents request duplication, allows for transaction rollbacks, and a more. Needless to say, it is very powerful, and one of the key infrastructure changes that will be going into the next version (12) of Mint.com.
The idea originally came to me, while looking at "The Callback Object and Scope" example in the Connection Utility documentation. The author creates a stub object to hold various useful functions related to the YAHOO.util.Connect.asyncRequest
. Taking this to the next level, we create an instantiatable object that encapsulates the AJAX request system.
I have broken this article into 3 parts, two articles to cover the AjaxObject and one day to cover AjaxManager. The second article will come out early next week, followed by the third later in the week. You can see the complete source code for more detailed comments and a working version.
Example 1: Constants and Internal Functions
// constants var Y = YAHOO, YU = YAHOO.util, CONN = YU.Connect, LANG = Y.lang, YD = YU.Dom, YE = YU.Event, LOGOUT_URL =logout.event?+ C.PARAM_NAME_NEXT_PAGE +=, // define known error codes ERROR_ABORTED = -1, ERROR_CODE_SESSION_TIMED_OUT = 1, ERROR_CODE_INVALID_PARAMETER = 2, ERROR_PAGE_NOT_FOUND = 404, // local variables _isUnloading = false, // Removes invalid chunks from a string, where an invalid chunk is more than one&in a row, ending with&, or?&. _cleanInvalidChunks = function(s) { var str = ( + s).replace(/&+/g,&).replace(/\?&/,?); return&=== str.charAt(str.length - 1) ? str.slice(0, -1) : str; }, // Stops the provided timer. _haltTimer = function(timer) { if (timer) {timer.cancel();} }, // Handles error logging. _logError = function(name, error) { if (! _isUnloading) { Y.log(name + ": " + error); } }, // Sets the status to unloading, so additional requests arent made while the page is unloading. _unloadingCallback = function() {_isUnloading = true;}, // Instantiates an AjaxObject. _F = function(conf) { var cfg = {}; LANG.augmentObject(cfg, _F.ATTR, true); LANG.augmentObject(cfg, conf || {}, true); if (! cfg.rId) {cfg.rId =yui-gen+ YAHOO.env._id_counter++;} this._cfg = cfg; YU.AjaxManager.register(this); }; YU.AjaxObject = _F; // this prevents AJAX requests from being made after the user leaves the current page YE.on(window,unload, _unloadingCallback); YE.on(window,beforeunload, _unloadingCallback);
The code in Example 1 creates a few constants that will be used later in the system, then several functions that will be leveraged later, followed by the AjaxObject constructor, and then registers two unload listeners. The error constants are defined by the developer (except -1 and 404, which are required), and can be sent by the server to indicate an error which AjaxObject should automatically handle. The functions are self-explainatory; except, that I would replace the Y.log
of _logError()
with your own logging sytem. The constructor takes an optional configuration object and applies the values to this._cfg
after applying the default values. It also registers the AjaxObject with AjaxManager, which manages all AjaxObjects. Lastly, the unload
and beforeunload
events are listened on, to update the internal isUnloading
value. This prevents AJAX requests from being sent while the page is unloading, which caused issues with the window.onerror
logging system used on Mint.com.
Example 2: Augmenting YAHOO.util.AjaxObject
// the acceptable types of responses from the server LANG.augmentObject(_F, { TYPE_JSON: text/json, TYPE_XML:text/xml, TYPE_XML_APP:application/xml}); // a constant of default configuration parameters _F.ATTR = { abortOnDuplicate: true, argument: null, cache: false, callback: null, data: null, failure: null, method:get, pollTimeout: 0, rId: null, rollback: null, scope: null, timeout: 10000, requestDelay: 0, type: null, url: null };
In Example 2 several constants are applied to YAHOO.util.AjaxObject
: the various acceptable response types, and the default configuration settings. The ATTR
shows all possible configuration parameters that can be set and their default values. These values can be overridden permanently when the AjaxObject is instantiated, or temporarily whenever startRequest
is called to actually make an AJAX request. Here is what these values mean:
Setting abortOnDuplicate
to true
tells AjaxObject to abort any existing request, whenever it makes a new request, preventing duplicate callback execution, but not necessarily duplicate requests to the server. The argument
will be passed through to the callback function, like when using the Connection Utility directly. Setting cache
to true
will cause Connection Utility to cache the request. The callback
is a function to execute when request is successfully. The data
can be null
for get
requests or either a simple object
, array
, or string
for post
requests (the AjaxObject will automatically convert them to a search string). The failure
is a function to execute if the AJAX request fails, in addition to the default failure logic. The method
should be either get
or post&rsquot;
. Setting pollTimeout
to a positive integer will cause AjaxObject to poll the configured URL until the callback
function returns true
. The rId
is a unique identifer for this AjaxObject. The rollback
is a function the developer can specify to execute a rollback when the request fails. The scope
is the execution context to execute the callback
callback function in. The timeout
is the amount of time to wait before the AjaxObject automatically aborts (default is 10 seconds). Setting requestDelay
to a positive integer causes AjaxObject to wait that many milliseconds before issuing its request; when used in conjunction with abortOnDuplicate
it will prevent duplicate requests from being sent to the server, however, it will prevent startRequest
from returning the YUI connection object. Set type
to one of the constants defined in Example 2 when expecting the AJAX request to return a specific response type. And set the url
whenever making any request (this must be provided or AjaxObject will throw an error when trying to execute startRequest
).
The next article will cover the YAHOO.util.AjaxObject.prototype
function and show an example of how to use AjaxObject.