building smart async functions for mobile

20
BUILDING SMART ASYNC FUNCTIONS FOR MOBILE Glan Thomas Mountain View JavaScript Meetup Group Aug 10, 2011

Upload: glan-thomas

Post on 01-Nov-2014

1.946 views

Category:

Technology


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Building Smart Async Functions For Mobile

BUILDING SMART ASYNC FUNCTIONS FOR MOBILE

Glan ThomasMountain View JavaScript Meetup Group

Aug 10, 2011

Page 2: Building Smart Async Functions For Mobile

TYPICAL ASYNC FUNCTIONS

getJSON(url, [data,] [success(data, textStatus, jqXHR),] [dataType])

get(url, [data,] [success(data, textStatus, jqXHR),] [dataType])

post(url, [data,] [success(data, textStatus, jqXHR),] [dataType])

Page 3: Building Smart Async Functions For Mobile

ASYNC PROBLEMS

• Requires an HTTP request

• Requires a network connection

• Cross domain origin

Page 4: Building Smart Async Functions For Mobile

OBJECTIVES

•Minimize HTTP requests

•Make things work even if you are offline

• Avoid cluttering up the app’s controllers with online/offline conditionals

• Preserve original API signatures

getJSON( url, [data,] [success,] [cache,] [filter,] [keyboardcat] )

Page 5: Building Smart Async Functions For Mobile

WHAT CAN WE DO?

•Cache - Keep a local copy of the data

•Queue - For sending to the server later

•Merge - Combine requests into one

• Filter - Transform the incoming data

•AB Testing - Provide different data for different users

•Versioning - Making sure you hit the right endpoints

Page 6: Building Smart Async Functions For Mobile

TECHNIQUES

• Interfaces - for utility objects

• Decorators - for augmenting async functions

• Delegation - to utility object

Page 7: Building Smart Async Functions For Mobile

INTERFACES

Cache Interface

• get(key)

• set(key, value)

• delete(key)

Queue Interface

• add(item)

• remove()

Page 8: Building Smart Async Functions For Mobile

DECORATORS

Page 9: Building Smart Async Functions For Mobile

WHAT JUST HAPPENED?

jQuery.get CacheDecorator getCached

Page 10: Building Smart Async Functions For Mobile

var cache = new Cache(),

myGet = jQuery.get;

myGet = new CacheDecorator(myGet, cache);

myGet(url, successFunction);

USAGE

Page 11: Building Smart Async Functions For Mobile

CACHE DECORATOR

var CacheDecorator = function (func, cache) { 'use strict'; return function (url, success) { var data = cache.get(url); if (data) { success(data, 'hit'); } else { func(url, function (data) { cache.set(url, data); if (typeof success === 'function') { success.apply(this, arguments); } }); } };};

Page 12: Building Smart Async Functions For Mobile

STACKING

var cache = new Cache(), filter = new Filter(),

myGet = jQuery.get;

myGet = new FilterDecorator(myGet, filter);

myGet = new CacheDecorator(myGet, cache);

myGet(url, successFunction);

Page 13: Building Smart Async Functions For Mobile

FILTER DECORATOR

var FilterDecorator = function (func, filter) { 'use strict'; return function (url, success) { func(url, function (data) { data = filter(url, data); if (typeof success === 'function') { success.apply(this, arguments); } }); };};

Page 14: Building Smart Async Functions For Mobile

QUEUE DECORATOR

var QueueDecorator = function (func, queue) { 'use strict'; return function (url, data, success) { queue.add({'func': func, 'args' : arguments}); success({}, 'queued'); };};

Page 15: Building Smart Async Functions For Mobile

TAKEAWAYS

• Use decorators to enhance existing asynchronous functions without altering their signatures.

•Delegate functionality to dedicated utility objects (Caching/Queuing).

•Define interfaces for utility objects.

• Stack decorators to combine functionality.

Page 16: Building Smart Async Functions For Mobile

SOME THINGS WE SKIPPED

• Cross domain origin

• Error and failure states

• Specific implementations of Cache and Queue classes (LocalStorage/SQLite)

• Enforcing of interfaces (see ‘Pro JavaScript Design Patterns’, Ross Harmes and Dustin Diaz, Apress, 2008)

Page 17: Building Smart Async Functions For Mobile

QUESTIONS?

Page 18: Building Smart Async Functions For Mobile

CACHE IMPLEMENTATIONCache.prototype = { set : function (key, value) { var package = {}; package.type = typeof value; package.value = (package.type === 'object') ? JSON.stringify(value) : value; localStorage[this._hash(key)] = JSON.stringify(package); }, get : function (key) { var package; if (this._exists(key)) { try { package = JSON.parse(localStorage[this._hash(key)]); } catch (e) { this.remove(key); return false; } return (package.type === 'object') ? JSON.parse(package.value) : package.value; } return false; }, remove : function (key) { if (this._exists(key)) { delete localStorage[this._hash(key)]; } }}

Page 19: Building Smart Async Functions For Mobile

QUEUE IMPLEMENTATIONvar Queue = function() {};Queue.prototype = new Array();

Queue.prototype.add = function (item) {this.push(item);

};Queue.prototype.remove = function () { return this.shift();};Queue.prototype.goOnline = function () { var self = this, success; if(item = this[0]) { success = item.args[2]; item.args[2] = function () { success.apply(this, arguments); self.remove(); self.goOnline(); }; item.func.apply(this, item.args); }};

var queue = new Queue();

document.body.addEventListener("online", function () { queue.goOnline();}, false);

Page 20: Building Smart Async Functions For Mobile

OFFLINE DECORATOR

var OfflineDecorator = function (func, offLine) { 'use strict'; return function (url, success) { if (offLine) { success({}, 'offline'); } else { func(url, function (data) { if (typeof success === 'function') { success.apply(this, arguments); } }); } };};