JavaScript Essential Patterns othree @ OSDC 2012
Who am I • othree • MozTW member • F2E at HTC • http://blog.othree.net
Evolution of the Web WWW Browser Wars Web Standards Web Applications Web 2.0 Mobile 1990 1995 2003 2005 2006 2010
Web Applications
Text
Problem to F2E • Large scale application never seen on Web
But • The problem F2Es face today already exists
What is Pattern • A general reusable solution to a commonly occurring problem within a given context in software design. http://en.wikipedia.org/wiki/Software_design_pattern
GOF Book, 1994
Browser Environment • Async • Event Driven • Async • Source Code from Internet • Async • Business Logic on Server
Patterns to Talk Today • Custom Event • Deferred • PubSub
Custom Event http://www.flickr.com/photos/swehrmann/6009646752
Event • Something happens to an element, to the main document, or to the browser window and that event triggers a reaction. http://www.yuiblog.com/blog/2007/01/17/event-plan/
Native Events • DOM Events • BOM Events • UI • load • UI logic • error • mutation • history • ... • ...
Problem of IE • Didn’t follow the W3C DOM standard • Memory leaks • Not support bubbling/capturing • ‘this’ is window, not element • ‘event’ is different http://www.quirksmode.org/blog/archives/2005/08/addevent_consid.html
Dean Edward’s Add Event • Manage callback functions • Fallback to elem.onevent = function () { ... } • Only one function for each event http://dean.edwards.name/weblog/2005/10/add-event2/
jQuery’s Event • Normalize event object • ‘trigger’ method to fire specific event
‘trigger’ Method • Can fire any event as you wish • Even none native event name works
Custom Event • An event name is defined by you, triggered by you
When to Trigger • State/Value change
Observer • Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. GoF Book
Example: Backbone • A driver model • A car model • Driver’s tension will get higher when shift gear
Driver var Driver = Backbone.Model.extend( defaults: { tension: 0 }, tensionUp: function () { this.set({ tension: this.get('tension') + 1 }); } );
Car var Car = Backbone.Model.extend( defaults: { gear: 'P' } );
Observer var driver = new Driver(), car = new Car(); car.on('change:gear', function () { driver.tensionUp(); }); //GO car.set({ gear: 1 });
Advantages • Loose coupling • Prevent nested codes
Deferred http://www.flickr.com/photos/gozalewis/3256814461/
History • a.k.a Promise • Idea since 1976 (Call by future) • Dojo 0.9 (2007), 1.5 (2010) • jQuery 1.5 (2011) • CommonJS Promises/A
What is Deferred • In computer science, future, promise, and delay refer to constructs used for synchronization in some concurrent programming languages. http://en.wikipedia.org/wiki/Futures_and_promises
Example: Image Loader function imgLoader(src) { var _img = new Image(), _def = $.Deferred(); _img.onload = _def.resolve; //success _img.onerror = _def.reject; //fail _img.src = src return _def; }
Use Image Loader imgLoader('/images/logo.png').done(function () { $('#logo').fadeIn(); }).fail(function () { document.location = '/404.html'; });
jQuery Deferred • Multiple callback functions • Add callbacks at any time • jQuery.when http://api.jquery.com/category/deferred-object/
Image Loader with Cache function imgLoader(src) { if (imgLoader[src]) { return imgLoader[src]; } var _img = new Image(), _def = $.Deferred(); imgLoader[src] = _def; _img.onload = _def.resolve; //success _img.onerror = _def.reject; //fail _img.src = src return _def; }
Use Image Loader imgLoader('/images/logo.png').done(function () { $('#logo').fadeIn(); }).fail(function () { document.location = '/404.html'; }); imgLoader('/images/logo.png').done(function () { App.init(); }); imgLoader('/images/logo.png').fail(function () { App.destroy(); });
jQuery.when $.when( $.getJSON('/api/jedis'), $.getJSON('/api/siths'), $.getJSON('/api/terminators') ).done(function (jedis, siths, terminators) { // do something.... });
Advantages • Manage callbacks • Cache results • $.when
PubSub http://www.flickr.com/photos/birdfarm/519230710/
Case • A module know when user signin • X,Y modules need to know when user signin • A should not fail when X or Y fails
Without PubSub
X signin signin A Y B Z
X,Y depends on A
PubSub Subscribe Event Only
X PubSub A Y B Z
subscribe ‘signin’ X PubSub subscribe A ‘signin’ Y B Z
X PubSub publish A ‘signin’ Y B Z
signin X PubSub signin A Y B Z
Publish/Subscribe • Mediator + Observer • Easy to implement
$(document).trigger('eventName'); // Using .on()/.off() from jQuery 1.7.1 //equivalent to $.publish('eventName') (function($) { $(document).on('eventName',...); var o = $({}); //equivalent to $.subscribe('eventName',...) $.subscribe = function() { o.on.apply(o, arguments); }; $.unsubscribe = function() { o.off.apply(o, arguments); }; $.publish = function() { o.trigger.apply(o, arguments); }; }(jQuery)); // Multi-purpose callbacks list object //Using Underscore and Backbone // Pub/Sub implementation: var myObject = {}; var topics = {}; _.extend( myObject, Backbone.Events ); jQuery.Topic = function( id ) { var callbacks, topic = id && topics[ id ]; //Example if ( !topic ) { callbacks = jQuery.Callbacks(); myObject.on('eventName', function( msg ) { topic = { console.log( 'triggered:' + msg ); publish: callbacks.fire, }); subscribe: callbacks.add, unsubscribe: callbacks.remove myObject.trigger('eventName', 'some event'); }; if ( id ) { topics[ id ] = topic; } } return topic; }; http://addyosmani.com/blog/jqcon-largescalejs-2012/
When to Use • Module and module have dependency but not really depend on it.
Example: Error Handler • An module to control the behavior when error occurs • All other module should call it when something went wrong • No module should fail because error handler fails
Error Handler Code //Error Handler $.subscribe('AJAXfail', function () { alert('Something wrong!!'); }); //Code $.get('/api/siths').fail(function () { $.publish('AJAXfail'); });
Advantages • Loose coupling • Scalability
Summary • Control async process using deferred • Modulize your application • Decouple using custom event • Decouple more using pubsub
Further Reading...
http://addyosmani.com/resources/essentialjsdesignpatterns/book/
http://shichuan.github.com/javascript-patterns/
http://leanpub.com/asyncjs
May the Patterns be with You
Questions?
Photos License • CC License • http://www.flickr.com/photos/sbisson/298160250/ • http://www.flickr.com/photos/gozalewis/3256814461/ • http://www.flickr.com/photos/birdfarm/519230710/ • Licensed by Author • http://www.flickr.com/photos/swehrmann/6009646752

Javascript essential-pattern

  • 1.
  • 2.
    Who am I •othree • MozTW member • F2E at HTC • http://blog.othree.net
  • 3.
    Evolution of theWeb WWW Browser Wars Web Standards Web Applications Web 2.0 Mobile 1990 1995 2003 2005 2006 2010
  • 4.
  • 5.
  • 10.
    Problem to F2E •Large scale application never seen on Web
  • 11.
    But • The problemF2Es face today already exists
  • 12.
    What is Pattern •A general reusable solution to a commonly occurring problem within a given context in software design. http://en.wikipedia.org/wiki/Software_design_pattern
  • 13.
  • 14.
    Browser Environment • Async • Event Driven • Async • Source Code from Internet • Async • Business Logic on Server
  • 15.
    Patterns to TalkToday • Custom Event • Deferred • PubSub
  • 16.
    Custom Event http://www.flickr.com/photos/swehrmann/6009646752
  • 17.
    Event • Something happensto an element, to the main document, or to the browser window and that event triggers a reaction. http://www.yuiblog.com/blog/2007/01/17/event-plan/
  • 18.
    Native Events • DOM Events • BOM Events • UI • load • UI logic • error • mutation • history • ... • ...
  • 19.
    Problem of IE •Didn’t follow the W3C DOM standard • Memory leaks • Not support bubbling/capturing • ‘this’ is window, not element • ‘event’ is different http://www.quirksmode.org/blog/archives/2005/08/addevent_consid.html
  • 20.
    Dean Edward’s AddEvent • Manage callback functions • Fallback to elem.onevent = function () { ... } • Only one function for each event http://dean.edwards.name/weblog/2005/10/add-event2/
  • 21.
    jQuery’s Event • Normalizeevent object • ‘trigger’ method to fire specific event
  • 22.
    ‘trigger’ Method • Canfire any event as you wish • Even none native event name works
  • 23.
    Custom Event • Anevent name is defined by you, triggered by you
  • 24.
    When to Trigger •State/Value change
  • 25.
    Observer • Define aone-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. GoF Book
  • 26.
    Example: Backbone • Adriver model • A car model • Driver’s tension will get higher when shift gear
  • 27.
    Driver var Driver =Backbone.Model.extend( defaults: { tension: 0 }, tensionUp: function () { this.set({ tension: this.get('tension') + 1 }); } );
  • 28.
    Car var Car =Backbone.Model.extend( defaults: { gear: 'P' } );
  • 29.
    Observer var driver =new Driver(), car = new Car(); car.on('change:gear', function () { driver.tensionUp(); }); //GO car.set({ gear: 1 });
  • 30.
  • 31.
    Deferred http://www.flickr.com/photos/gozalewis/3256814461/
  • 32.
    History • a.k.a Promise •Idea since 1976 (Call by future) • Dojo 0.9 (2007), 1.5 (2010) • jQuery 1.5 (2011) • CommonJS Promises/A
  • 33.
    What is Deferred •In computer science, future, promise, and delay refer to constructs used for synchronization in some concurrent programming languages. http://en.wikipedia.org/wiki/Futures_and_promises
  • 34.
    Example: Image Loader functionimgLoader(src) { var _img = new Image(), _def = $.Deferred(); _img.onload = _def.resolve; //success _img.onerror = _def.reject; //fail _img.src = src return _def; }
  • 35.
    Use Image Loader imgLoader('/images/logo.png').done(function() { $('#logo').fadeIn(); }).fail(function () { document.location = '/404.html'; });
  • 36.
    jQuery Deferred • Multiplecallback functions • Add callbacks at any time • jQuery.when http://api.jquery.com/category/deferred-object/
  • 37.
    Image Loader withCache function imgLoader(src) { if (imgLoader[src]) { return imgLoader[src]; } var _img = new Image(), _def = $.Deferred(); imgLoader[src] = _def; _img.onload = _def.resolve; //success _img.onerror = _def.reject; //fail _img.src = src return _def; }
  • 38.
    Use Image Loader imgLoader('/images/logo.png').done(function() { $('#logo').fadeIn(); }).fail(function () { document.location = '/404.html'; }); imgLoader('/images/logo.png').done(function () { App.init(); }); imgLoader('/images/logo.png').fail(function () { App.destroy(); });
  • 39.
    jQuery.when $.when( $.getJSON('/api/jedis'), $.getJSON('/api/siths'), $.getJSON('/api/terminators') ).done(function (jedis, siths, terminators) { // do something.... });
  • 40.
    Advantages • Manage callbacks •Cache results • $.when
  • 41.
    PubSub http://www.flickr.com/photos/birdfarm/519230710/
  • 42.
    Case • A moduleknow when user signin • X,Y modules need to know when user signin • A should not fail when X or Y fails
  • 43.
  • 44.
    X signin signin A Y B Z
  • 45.
  • 46.
  • 47.
    X PubSub A Y B Z
  • 48.
    subscribe ‘signin’ X PubSub subscribe A ‘signin’ Y B Z
  • 49.
    X PubSub publish A ‘signin’ Y B Z
  • 50.
    signin X PubSub signin A Y B Z
  • 51.
    Publish/Subscribe • Mediator +Observer • Easy to implement
  • 52.
    $(document).trigger('eventName'); // Using .on()/.off() from jQuery 1.7.1 //equivalent to $.publish('eventName') (function($) { $(document).on('eventName',...); var o = $({}); //equivalent to $.subscribe('eventName',...) $.subscribe = function() { o.on.apply(o, arguments); }; $.unsubscribe = function() { o.off.apply(o, arguments); }; $.publish = function() { o.trigger.apply(o, arguments); }; }(jQuery)); // Multi-purpose callbacks list object //Using Underscore and Backbone // Pub/Sub implementation: var myObject = {}; var topics = {}; _.extend( myObject, Backbone.Events ); jQuery.Topic = function( id ) { var callbacks, topic = id && topics[ id ]; //Example if ( !topic ) { callbacks = jQuery.Callbacks(); myObject.on('eventName', function( msg ) { topic = { console.log( 'triggered:' + msg ); publish: callbacks.fire, }); subscribe: callbacks.add, unsubscribe: callbacks.remove myObject.trigger('eventName', 'some event'); }; if ( id ) { topics[ id ] = topic; } } return topic; }; http://addyosmani.com/blog/jqcon-largescalejs-2012/
  • 53.
    When to Use •Module and module have dependency but not really depend on it.
  • 54.
    Example: Error Handler •An module to control the behavior when error occurs • All other module should call it when something went wrong • No module should fail because error handler fails
  • 55.
    Error Handler Code //ErrorHandler $.subscribe('AJAXfail', function () { alert('Something wrong!!'); }); //Code $.get('/api/siths').fail(function () { $.publish('AJAXfail'); });
  • 56.
  • 57.
    Summary • Control asyncprocess using deferred • Modulize your application • Decouple using custom event • Decouple more using pubsub
  • 58.
  • 61.
  • 62.
  • 63.
  • 64.
    May the Patternsbe with You
  • 65.
  • 66.
    Photos License • CCLicense • http://www.flickr.com/photos/sbisson/298160250/ • http://www.flickr.com/photos/gozalewis/3256814461/ • http://www.flickr.com/photos/birdfarm/519230710/ • Licensed by Author • http://www.flickr.com/photos/swehrmann/6009646752