socket-sync.js | |
---|---|
var Backbone = require('backbone'),
_ = require('underscore'),
socket = require('./socket'); | |
requestId counter to insure sync message are paired correctly | var counter = 0; |
stolen from Backbone let you safely get the value of the property applying function for value, if function provided | function getValue (object, prop) {
if (!(object && object[prop])) return null;
return _.isFunction(object[prop]) ? object[prop]() : object[prop];
}; |
mockey patch this flag so that we can distinguish between Model and Collection for the server when the socket sync happens, the server can know collection vs singleton | Backbone.Collection.prototype.isCollection = true;
var modelRegistryById = {};
function registerModelForUpdates(model){
console.log('registering model:', model.id);
if (modelRegistryById[model.id] == undefined){ |
hold a reference to the model TODO: add unsubscribe, dangling ref | modelRegistryById[model.id] = [model];
} else { |
add to the list of models by registerd to this id | if (_.indexOf(modelRegistryById[model.id], model) == -1){
modelRegistryById[model.id].push(model);
}
}
}
function updateAllModels(id, attrs){
var models = modelRegistryById[id];
_.each(models, function(model){
console.log('instance change notified', model.id);
model.set(attrs);
});
}
Backbone.sync = function(method, model, options) { |
TODO options.timeout? | var params = getValue(model, 'params') || {},
controller = getValue(model, 'controller'),
requestId = counter++;
var syncRequest = {
requestId: requestId,
controller: controller,
method: method,
model: model.toJSON(),
params: _.extend(_.clone(params), options)
}; |
replace collection read and index to disambiguate singleton and collection | if (model.isCollection) { |
map 'read' on collection to 'index' | syncRequest.method = 'index';
} else if (syncRequest.method == 'delete') { |
map 'delete' to 'destroy' since 'delete' is a keyword | syncRequest.method = 'destroy';
}
socket.emit('syncRequest', syncRequest); |
TODO: need to handle errors | socket.once('syncResponse-'+ requestId, function (res) {
if (res.error) {
options.error(res.error);
} else if (res.success) { |
side-effect model attrs first to deal with initial id setting | console.log('sycn response with update');
options.success(res.success); |
make sure we only hook callback once per model | registerModelForUpdates(model); |
when sync is called an implicit subscription for server changes is established set up automated subsciption from server which will trigger 'change' event | socket.on('instanceChange', function(attrs){
console.log('client recvd instanceChange message');
updateAllModels(attrs.id, attrs)
});
}
});
};
|