Building Stateful Modules with Events and Promises
DOMManipulation
patrickCAMACHO
Beyond
Friday, June 14, 13
CrashlyticsforAndroid&iOS
Friday, June 14, 13
Friday, June 14, 13
Friday, June 14, 13
Friday, June 14, 13
Friday, June 14, 13
Railsto Backbone.
Friday, June 14, 13
Whatdidwehave?
Model
Backbone.Model
Backbone.Collection
Routing
Backbone.Router,
Backbone.History
Views
Backbone.Views
Events
Backbone.Events
MV* components
Friday, June 14, 13
What’smissing?
Friday, June 14, 13
TransitioningPagestoStates.
Friday, June 14, 13
Piecemeal.
App
State
Friday, June 14, 13
Piecemeal.
App
Router
State
Friday, June 14, 13
Piecemeal.
App
Router Directors
State
Friday, June 14, 13
Piecemeal.
App
Router Directors
State
Friday, June 14, 13
Addingamodal.
Friday, June 14, 13
Friday, June 14, 13
Neededbetterstructure.
• Builtonsingleflowand
states
• Modaldidn’tfitflow
• Backtothe
drawingboard
App
Router Directors
State
Friday, June 14, 13
Neededbetterstructure.
• Builtonsingleflowand
states
• Modaldidn’tfitflow
• Backtothe
drawingboard
App
Router Directors
State
Settings
Friday, June 14, 13
Thebirthofthe“module”.
• Entirelyindependentpiecesoffunctionality
• Itcouldaccepteventsandstart/stopitself
State
this.$('.settings').click(function(){
CLS.Components.Settings.trigger('start');
});
Settings
this.$('.overlay').click((function(){
this.trigger('stop');
}).bind(this));
Friday, June 14, 13
Asyncbehavior.
Friday, June 14, 13
Asyncbehaviorinstates.
• Fetchingdata,animations,etc
• Wanttoshutanythingdownwhenstopping
Settings
Server
(rendering)
Friday, June 14, 13
Promises.
• $.Promisesand$.Deferreds
• .done,.fail,.always
• .resolve,.reject
fetch1 = $.get('data.json');
fetch2 = $.get('data2.json');
fetch1.done(function(){ console.log(‘success!’); }
fetch2.always(function(){ console.log(‘complete!’); }
$.when(fetch1, fetch2).fail(function(){
console.log(‘fail!’);
});
Friday, June 14, 13
UsingwithComponents.
Settings.start = function() {
this.stopDeferred = $.Deferred();
fetch1 = $.get('data.json');
this.stopDeferred.done(fetch1.abort);
fetch2 = $.get('data2.json');
this.stopDeferred.done(fetch2.abort);
$.when(fetch1, fetch2).done(this.render.bind(this));
}
Settings.stop = function() {
this.stopDeferred.resolve();
}
Friday, June 14, 13
Goodintheshortrun.
• Onlyhadoneapplication
• Componentslived
forever
• Singletonshidthe
problems
Settings Alert Center
RealTime Analytics
Friday, June 14, 13
Multipleapplications.
Friday, June 14, 13
Distinctfunctionality.
Friday, June 14, 13
Distinctfunctionality.
Friday, June 14, 13
Multipleapplications.
• Lostcoreassumptionofapage-longapp
• Appsbegantolookmoreandmorelikemodules
Onboarding
Onboarding.start : function(){
if(this._isActive) return;
...
this._isActive = true;
}
Onboarding.stop : function(){
if(!this._isActive) return;
...
this._isActive = false;
}
Friday, June 14, 13
Multipleapplications.
Apps
Router Directors
State
Friday, June 14, 13
Persistentfunctionalty.
• Componentsneededtobestarted/stoppedbyappson
start/stop
• Notallshouldbestartedorstopped
• Backtoheavyconditionals
if(nextApp === 'onboard') {
CLS.Components.Settings.trigger('stop');
CLS.Components.AlertCenter.trigger('stop');
} else if(nextApp === 'logout') {
CLS.Components.Settings.trigger('stop');
CLS.Components.AlertCenter.trigger('stop');
CLS.Components.RealTime.trigger('stop');
} else if...
Friday, June 14, 13
Findingapattern.
Friday, June 14, 13
Sameproblem,differentlevels.
• Eventing
• Start
• Stop
• Dependencies
App
State State
Component Component Component
Friday, June 14, 13
Isolatingknowledge.
Friday, June 14, 13
Toomanydirectreferences.
• Don’tknowoutsideinformation
• Clearestinstoppingdependencies
if(nextApp === 'onboard') {
CLS.Components.Settings.trigger('stop');
CLS.Components.AlertCenter.trigger('stop');
} else if(nextApp === 'logout') {
CLS.Components.Settings.trigger('stop');
CLS.Components.AlertCenter.trigger('stop');
CLS.Components.RealTime.trigger('stop');
} else if...
Friday, June 14, 13
Eventingwitharguments.
Onboarding Dashboard
Dashboard.start = function() {
Onboarding.trigger('stop', this.dependencies);
}
Onboarding.stop = function(dependencies) {
if(dependencies == null) { dependencies = [] }
this.dependencies.forEach(function(dependencies){
if(dependencies.indexOf(dependency) < 0) {
dependency.trigger('stop', dependencies);
}
});
}
Friday, June 14, 13
• Wantedevents,butnottheknowledge
Stilltightlycoupled.
Dashboard.start = function() {
Onboarding.trigger('stop', this.dependencies);
LoggedOut.trigger('stop', this.dependencies);
}
Friday, June 14, 13
Simplifyfunctionality.
Friday, June 14, 13
Usingavent.
• Allofthesepiecesareusingevents
• Isolatethatfunctionalitytoasingleunit
Vent
Vent = function() {...}
Vent.prototype.on = function() {...}
Vent.prototype.one = function() {...}
Vent.prototype.off = function() {...}
Vent.prototype.trigger = function() {...}
Friday, June 14, 13
Sharingavent.
OnboardingDashboard Vent
Onboarding.start = function() {
this.vent.trigger('app:dashboard:stop', this.dependencies);
this.vent.trigger('app:loggedOut:stop', this.dependencies);
}
Friday, June 14, 13
Smartsubscriptions.
Dashboard.start = function(vent) {
this.vent.trigger('app:onBeforeStart', this.dependencies);
this.vent.one('app:onBeforeStart', this.stop.bind(this));
}
Onboarding.start = function(vent) {
this.vent.trigger('app:onBeforeStart', this.dependencies);
this.vent.one('app:onBeforeStart', this.stop.bind(this));
}
OnboardingDashboard Vent
Friday, June 14, 13
Sharinginformation.
Friday, June 14, 13
• Sharedatabetweenmodules
• Useventtoregisterresponsesandrequest
Synchronousdatareturns.
VentDashboard Settings
Friday, June 14, 13
Dashboard.start = function() {
this.currentApplication = ‘foo bar’
this.vent.setResponse(
'current_application',
(function(){ return this.currentApplication; }).bind(this);
);
}
Settings.start = function() {
app = this.vent.requestResponse('current_application');
}
Synchronousdatareturns.
Friday, June 14, 13
Tyingitalltogether.
Friday, June 14, 13
Modularizeallthethings!
• Isolatedfunctionality
• Start/stop
• Managingdependencies
• Eventing
• Asyncbehavior
Friday, June 14, 13
Modularizeallthethings!
Component
App
State
• Isolatedfunctionality
• Start/stop
• Managingdependencies
• Eventing
• Asyncbehavior
Friday, June 14, 13
Vent
Rethinkingtheflow.
Friday, June 14, 13
Vent
Rethinkingtheflow.
Router
Friday, June 14, 13
ComponentsVent
Rethinkingtheflow.
Apps
Router
Friday, June 14, 13
Vent
ComponentsVent
Rethinkingtheflow.
Apps
Router
States
Friday, June 14, 13
Vent
Vent
ComponentsVent
Rethinkingtheflow.
Apps
Router
States
States
Friday, June 14, 13
Makingityours
• Managecomplexityandscale
• Isolatefunctionalityintomodules
• Managedependencies
• Allowmodulestocommunicatethroughavent
Friday, June 14, 13
YOUpatrickCAMACHO
Thank
try.crashlytics.com/jobs
Friday, June 14, 13

Beyond DOM Manipulations: Building Stateful Modules with Events and Promises