YUI DataSource with dynamic oRequest

I preface this by asserting that I consider myself expert neither in YUI nor in JavaScript. There may be a better way to do this.

YUI (which I love) has an excellent abstract DataSource component that normalizes requests for data to something compatible with all their widgets. I find it generally useful as well, even when I'm not using, for example, a YUI DataTable to display data.

Last weekend I wrote a UI notification subsystem for Zenoss, based on YUI and Yowl. I used a DataSource to handle communication with the server. DataSources can be told to poll the server periodically, using the setInterval method:

myDataSource.setInterval(1000*60, "?var=123", callback)

This is all well and good, but in my case, I needed that second argument (oRequest) to be different each time, based on previous server responses; once setInterval is called, however, the same request parameters are used each time.

I got around this by writing an object extending XHRDataSource that would accept a callable for oRequest, which would be called each time it made an external connection. Turned out to be very simple (although I ran into "too much recursion" bug, described here. I used the fix at the end of the thread to get around it):

var Y = YAHOO.util; // Internal shortcut to save typing and lookups
CallableReqDS = function(oLiveData, oConfigs) {
// Workaround for bug #2176072 in YUI 2.6.0
this.constructor = Y.XHRDataSource;
// Chain constructors
CallableReqDS.superclass.constructor.call(this, oLiveData, oConfigs);
// Set constructor back (also part of fix)
this.constructor = CallableReqDS;
YAHOO.lang.extend(CallableReqDS, Y.XHRDataSource);

CallableReqDS.prototype.makeConnection = function(oRequest, oCallback, oCaller) {
if (typeof(oRequest)=='function') oRequest = oRequest();
CallableReqDS.superclass.makeConnection.call(this, oRequest, oCallback, oCaller)

Trivial, really, but it got the job done.

UPDATE: Here's an example. Let's say you want to defeat IE's draconian caching. Standard way to do this is to tack on a unique query string for each request, which you can't do with the default XHRDataSource, because the query string can't change from request to request when using setInterval. So you use this instead:

function getCacheBustingString(){
return "?ms=" + new Date().getTime()
var myDS = new CallableReqDS("/path/to/myurl");

myDS.setInterval(60, getCacheBustingString, callback)

That way the cache buster will be unique for each request.


Post a Comment