Skip to content

Instantly share code, notes, and snippets.

@oobleck
Last active August 29, 2015 14:16
Show Gist options
  • Save oobleck/90cc321bc799a2ff656b to your computer and use it in GitHub Desktop.
Save oobleck/90cc321bc799a2ff656b to your computer and use it in GitHub Desktop.
Backbone long polling module
/**
* Long Polling module for Backbone.
*
* @requires jQuery >= 1.7
* @param {Library} $ jQuery
* @param {Library} Backbone Backbone
* @demo http://codepen.io/oobleck/pen/dPjYXo?editors=101
* @example
* // Assuming we're in a Backbone.View:
* this.longPoll(opts)
*
* // Or somewhere else in Backbone besides a view
* Backbone.longPoll.call(this, options);
*/
;(function($, Backbone, undefined) {
// Bail early if Backbone isn't present
if (!Backbone) { return false; }
var eventNamespace = 'polling';
/**
* Config object for the long polling operation. It is a superset of the
* config object for $.ajax
*
* All defaults can be overridden in the `opts` Object passed to this plugin,
* along with any other jQuery XHR config options you need in your polling
* request.
*
* @name defaults
* @readonly
* @namespace
* @property {Object} defaults Default values for the polling
* operation.
* @property {Number} defaults.frequency The frequency, in seconds, to
* repeat the polling operation.
* @property {Function} defaults.onSuccess The method to execute on successful
* response from the server.
* @property {Function} defaults.onError The method to execute on failed
* response from the server.
* @property {String} defaults.type jqXHR request type property.
* @property {String} defaults.dataType jqXHR dataType prop of the expected
* response.
*/
var defaults = {
frequency : 3,
onSuccess : null,
onError : null,
type : 'get',
dataType : 'json',
url: null
};
// Detect Object.freeze and freeze it!
Object.freeze && Object.freeze(defaults);
/**
* Method for generating the namespaced event type
*
* @param {String} type The type of the event
* @return {String} The namespaced event type
*/
function _nsEvent(type) {
return [eventNamespace, type].join(':');
}
/**
* Generic long polling utility for Backbone
*
* @param {Object} opts Configuration object for operation. See `defaults`
* for example. This object is passed to $.ajax and
* accepts the same options.
* @return {$XHR} The jqXHR Object we're polling with
*/
function _longPoll(opts) {
var _this = this;
var opts = $.extend(true, {}, defaults, opts);
var goAhead = true;
var $xhr, timeout;
_this.abort = function() {
_kill()
_trigger(_nsEvent('abort'));
}
/**
* Kills the polling operation
*
* @return {Object} The Backbone object on which longPolling is called
*/
function _kill() {
$xhr && $xhr.abort();
timeout && clearTimeout(timeout);
_trigger('stop');
return _this;
}
/**
* Convienience method that wraps Backbone.trigger with out namespaced
* events.
*
* @return {Object} The Backbone _this object
*/
function _trigger() {
var args = Array.prototype.slice.call(arguments, 0);
var eventName = _nsEvent(args[0]);
var parameters = args[1] || null
return _this.trigger(eventName, parameters);
}
/**
* The guts of the long polling operation
*
* @return {$XHR} The jqXHR Object
*/
function _poll() {
$xhr = $.ajax(opts)
.success(function(resp) {
_kill();
// Do we have an onSuccess method?
if (goAhead && opts.onSuccess) {
goAhead = opts.onSuccess(resp);
} else {
goAhead = false;
}
// Are we cleared to continue?
if (goAhead) {
_trigger('continue', resp);
timeout = setTimeout(_poll, (opts.frequency || 0.25) * 1000);
} else {
_trigger('done', resp);
return resp;
}
})
.error(function(resp) {
_trigger('error', resp);
_kill();
opts.onError && opts.onError(resp);
});
return $xhr;
}
return _poll();
};
Backbone.longPoll = _longPoll;
Backbone.View.prototype.longPoll = Backbone.longPoll;
}(jQuery, Backbone));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment