backbone-async-event v0.5.0
backbone-async-event
Do more than what the default Backbone Model/Collection request event does for you. The primary benefits are
- Use events to bind to
success/error/completeevents for each request (and an additionaldataevent) - Emit type specific XHR events to allow for focused binding
- Give ability to see if a model currently has any pending XHR activity
- Provide a global event bus to bind to all Model/Collection XHR activity
- Allow requests to be intercepted to, for example, return cached content
- Provide an additional
dataevent to intercept and override response data before it is returned to the Model/Collection - Provide event forwarding capabilities so other objects can simulate XHR activity to match another Model/Collection
- Make all event names and additional attributes overrideable to meet the needs of your particular project
- Give external entities a way to monitor ajax activity on your Collections and Models
Sections
General Usage Examples
Bind to a model to listen to all XHR activity
model.on('xhr', function(method, context) {
// method is "read", "save", or "delete" or custom (Backbone.sync method)
// context is a Backbone.Events to bind to XHR lifecycle events
context.on('complete', function(type, {type specific args}) {
// type will either be "success" or "error" and the type specific args are the same as what is provided to the respective events
// this will be called when the XHR succeeds or fails
});
context.on('success', function(model) {
// this will be called after the XHR succeeds
});
context.on('error', function(model, xhr, type, error) {
// this will be called if the XHR fails
});
});Bind to a model to listen to only fetches
model.on('xhr:read', function(context) {
...
});Override the XHR payload or cache it
model.on('xhr', function(method, context) {
context.on('data', function(data, status, xhr, context) {
// wrap the response as a "response" attribute
context.response = { response: data };
// cache the response
if (method === 'read') {
_cacheFetchResponse(JSON.stringify(data));
}
});
});Intercept a request and return a cached payload
Backbone.xhrEvents.on('xhr', function(method, model, context) {
var url = context.options.url;
if (context.method === 'read') {
var cachedResult = _getFetchCache(url);
if (cachedResult) {
context.intercept = function(options) {
options.success(JSON.parse(cachedResult), 'success');
}
}
}
});Make a successful XHR look like a failure
model.on('xhr', function(method, context) {
context.on('data', function(data, status, xhr, context) {
if (!context.preventDefault) {
// we don't want to call success/error callback more than once
context.preventDefault = true;
// provide the parameters that you would have wanted coming back directly from the $.ajax callback
context.options.error(...);
}
});
});Set a default timeout on all XHR activity
Backbone.xhrEvents.on('xhr', function(method, model, context) {
context.options.timeout = 3000;
});Determine fetch status of a model
model.fetch();
!!model.xhrActivity === true;
// model fetch complete now
!!model.xhrActivity === false;
// if the model fetch succeeded
model.hasBeenFetched === true;
model.hadFetchError === false;
// if the model fetch has failed...
model.hadFetchError === true;
model.hasBeenFetched === false;Forward xhr events to another model (source model will continue to emit xhr events as well)
// forward all events
Backbone.forwardXhrEvents(sourceModel, receiverModel);
// stop forwarding all events
Backbone.stopXhrForwarding(sourceModel, receiverModel);
// forward events for a specific Backbone.sync method
Backbone.forwardXhrEvents(sourceModel, receiverModel, 'read');
// stop forwarding all events
Backbone.stopXhrForwarding(sourceModel, receiverModel, 'read');
// forward events *only while the callback function is executed*
Backbone.forwardXhrEvents(sourceModel, receiverModel, function() {
// any XHR activity that sourceModel executes will be emitted by
// receiverModel as well
});Request Context
All XHR events provide a context as a parameter. This is an object extending Backbone.Events and is used to bind to the XHR lifecycle events including
- success: when the XHR has completed sucessfully
- error: when the XHR has failed
- complete: when the XHR has either failed or succeeded
- data: before the model has handled the response
In addition, the following read only attributes are applicable
- options: the Backbone.ajax options
- xhr: the actual XMLHttpRequest
- method: the Backbone.sync method
- model: the associated model
These attributes can be set on the context to alter lifecycle behavior
- intercept: set this value with a callback function(options) which will prevent further execution and execute the callback
- preventDefault: set this value as true when binding to the 'data' event if you want to alter success/error behavior (you must call options.success or options.error manually)
Overrides
Almost all event names and model/global attributes can be overridden to suit your needs.
- Backbone.xhrCompleteEventName: the event triggered on a model/collection when all XHR activity has completed (default:
xhr:complete) - Backbone.xhrModelLoadingAttribute: the model attribute which can be used to return an array of all current XHR request events and determind if the model/collection has current XHR activity (default:
xhrActivity) - Backbone.xhrEventName: the event triggered on models/collection and the global bus to signal an XHR request (default:
xhr) - Backbone.xhrGlobalAttribute: global event handler attribute name (on Backbone) used to subscribe to all model xhr events (default:
xhrEvents)
API: Events
Model / Collection events
"xhr" (method, context)
- method: the Backbone sync method (by default, "read", "update", or "delete")
- context: the request context (see "Request Context" section)
Emitted when any XHR activity occurs
model.on('xhr', function(method, context) {
// method is "read", "save", or "delete" or custom (Backbone.sync method)
// context is a Backbone.Events to bind to XHR lifecycle events
context.on('complete', function(type, {type specific args}) {
// type will either be "success" or "error" and the type specific args are the same as what is provided to the respective events
// this will be called when the XHR succeeds or fails
});
context.on('success', function(model) {
// this will be called after the XHR succeeds
});
context.on('error', function(model, xhr, type, error) {
// this will be called if the XHR fails
});
});"xhr:{method}" (context)
- method: the Backbone sync method (by default, "read", "update", or "delete")
- context: the request context (see "Request Context" section)
Emitted when only XHR activity matching the method in the event name occurs
model.on('xhr:read', function(method, context) {
...
});"xhr:complete" ()
Emitted when any XHR activity has completed and there is no more concurrent XHR activity
Backbone.xhrEvents (global events)
"xhr" (method, model, context)
- method: the Backbone sync method (by default, "read", "update", or "delete")
- model: the associated model
- context: the request context (see "Request Context" section)
Emitted when any XHR activity occurs
"xhr:{method}" (model, context)
- model: the associated model
- context: the request context (see "Request Context" section)
Emitted when only XHR activity matching the method in the event name occurs
API
Backbone
forwardXhrEvents (sourceModel, destModel, method) or (sourceModel, destModel, autoStopFunc)
- sourceModel: the originator model of the XHR events
- destModel: the receiver or proxy of the source model XHR events
- method: the optional Backbone.sync method to filter the forwarded events
- autoStopFunc: callback function that, if provided, will stop the forwarding after the function completes execution
Forward XHR events that originate in sourceModel to destModel. These events will also be emitted in sourceModel as well.
This can be useful if you have a composite model containing sub-models and want to aggregate xhr activity to the composite model.
var CompositeModel = Backbone.Model.extend({
initialize: function() {
// when model1 or model2 have xhr activity, "this" will expose the same xhr events
Backbone.Model.prototype.initialize.apply(this, arguments);
this.model1 = new Backbone.Model();
Backbone.forwardXhrEvents(this.model1, this);
this.model2 = new Backbone.Model();
Backbone.forwardXhrEvents(this.model2, this);
}
});stopXhrForwarding (sourceModel, destModel, method)
- sourceModel: the originator model of the XHR events
- destModel: the receiver or proxy of the source model XHR events
- method: the optional Backbone.sync method to filter the forwarded events
Stop forwarding XHR events. This must match a previous forwardXhrEvents call.