AJAX Poller

A friend of mine needed a simple AJAX polling system, so I developed the AjaxPoller widget for him. The object is instantiated with a configuration object, which should include at the very least the URL to poll (url). Additionally, the developer can optionally specify: the length of time before the AJAX message times out (timeout), the length of time to wait between polls (period), a function to trigger when to stop polling dymanically (stopfx), and assign subscribers to any of the three CustomEvents (onPoll, onStart, onStop).

Example: AjaxPoller

(function() {
// constants
var _YU = YAHOO.util,
	_YL = YAHOO.lang,
	_CE = _YU.CustomEvent,
	_YC = YAHOO.util.Connect;
	
Core.Controller.AjaxPoller = function(conf) {
	var _cfg = _YL.isObject(conf) ? conf : {};

	if (! _YL.isNumber(_cfg.period)) {_cfg.period = 5000;} // default is 5 seconds
	if (! _YL.isNumber(_cfg.timeout)) {_cfg.timeout = 10000;} // default is to abort AJAX after 10 seconds
	if (! _YL.isFunction(_cfg.stopfx)) {_cfg.stopfx = function() {};}
	if (! _YL.isString(_cfg.url)) {_cfg.url = ;}

	this._cfg = _cfg;
	this.onPoll = new _CE(AjaxPoller.poll, null, false, _CE.FLAT);
	this.onStart = new _CE(AjaxPoller.start, null, false, _CE.FLAT);
	this.onStop = new _CE(AjaxPoller.stop, null, false, _CE.FLAT);

	if (_YL.isFunction(_cfg.onPoll)) {this.onPoll.subscribe(_cfg.onPoll);}
	if (_YL.isFunction(_cfg.onStart)) {this.onStart.subscribe(_cfg.onStart);}
	if (_YL.isFunction(_cfg.onStop)) {this.onStop.subscribe(_cfg.onStop);}
};

Core.Controller.AjaxPoller.prototype = {

	onPoll: null,

	onStart: null,

	onStop: null,

	_cfg: null,

	_timeoutId: null,

	_transaction: null,

	start: function() {
		var _that = this;
		_that.onStart.fire(this);

		var fx = function() {
			_that._transaction = _YC.asyncRequest(GET, _that._cfg.url, {success: function(o) {
				_that.onPoll.fire(o);

				if (_that._cfg.stopfx(o)) {
					_that.stop(o);
				}
				else {
					_that._timeoutId = setTimeout(fx, _that._cfg.period);
				}
			}, failure: fx, timeout: _that._cfg.timeout});
		};

		fx();
	},

	stop: function() {
		if (this._transaction && this._transaction) {this._transaction.conn.abort();}
		if (this._timeoutId) {clearTimeout(this._timeoutId);}
		this.onStop.fire.apply(this.onStop, arguments);
	},

	updateUrl: function(url) {
		this._cfg.url = url;
	}
};
	
})();

Once the poller has been instantiated, simply call the start method to begin the system polling. Immediately upon calling the start method, the onStart CustomEvent fires, allowing developers to make any setup changes. Then the first AJAX request is made, and the onPoll CustomEvent fires after each response, passing the response object to any subscribers. The same response object is then passed to the stopfx, which should return true if the polling should be terminated. Otherwise, the system continues to poll until the developer/user triggers a stop. There the onStop CustomEvent fires, passing the response object, if terminated by the stopfx or null if terminated by the developer. If the url changes over time, then the updateUrl method should be called to modify the internal URL pointer.

Although the configuration object is exposed by the pseudo-private variable _cfg, modifying it or any of the other pseudo-private variables directly should be avoided. I have put together a demo page so you can play with the system.