Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Web app with functional programming

Web app with functional programming

Yu I.

June 27, 2014
Tweet

More Decks by Yu I.

Other Decks in Programming

Transcript

  1. In case of another Tumblr photo viewer » Made with:

    » D3.js (as DOM shorthands) » Underscore (as functional toolchain) » Q (as Promise object) » Think of what functional is
  2. D3.js as DOM shorthands » Bare DOM APIs are too

    verbose... » DOM APIs are object-oriented and should be wrapped as functional to be cool! » DOM shorthands will be reinventing wheel of jQuery... » Functions of jQuery are more like procedural and don't seem cool... » Functions of D3.js seems declarative and so cool!
  3. Underscore as functional toolchain » Very useful in case to

    read JSONs from ReST APIs » "Functional JavaScript" says Underscore is promising to be functional
  4. Q as Promise object » Asynchronous process needs any wrapper

    to be functional » Q is portable Promise implementation for client- and server-sides
  5. Idempotent function f (a, b) { return a + b;

    } f(1, 2); // => 3 Same result as always!
  6. Changed var x = 1; function f (a, b) {

    return a + b + x; } f(1, 2); // => 4 Result depends on the value of x
  7. Idempotent Promise object function submit (query) { var dfr =

    Q.defer(), form = d3.select('.search'), input = form.select('.search__input'); if (query) { _.defer(function () { input.property('value', query); form.classed({ 'position--in': false, 'position--out': true }); dfr.resolve(query); }); } else { form.on('submit', function (d, i) { var value = input.property('value'); d3.event.preventDefault(); form.on('submit', null); form.classed({ 'position--in': false, 'position--out': true }); global.location.hash = '#/' + global.encodeURIComponent(value); dfr.resolve(value); }); } return dfr.promise; }
  8. Chaining Promise objects function init () { Q.all([ helper.dom(), helper.sleep(1500)

    ]) .then(load) // Initial process .then(hash) .then(submit) // Repeated process .then(api) .then(cache) .then(show); } Easy to read what is proceeding!
  9. Reuse of chaining Promises function show () { submit() //

    Repeated process .then(api) .then(cache) .then(show); } Easy to build them up again!
  10. Wrap with Object-oriented Class class Blog extends helper.mixOf helper.Base, EventEmitter

    constructor: (domain, consumerKey) -> super() @consumerKey_ = consumerKey @domain_ = domain @total_ = 20 destroy: => @removeAllListeners() request: (type, offset=0) => consumerKey = @get 'consumerKey' domain = @get 'domain' uri = "http://api.tumblr.com/v2/blog/" uri += "#{domain}/posts/#{type}?api_key=#{consumerKey}&offset=#{offset}" done = (data) => if 200 is data.meta.status @set 'total', data.total_posts return @emit 'load', data.response @emit 'error', new Error(data.meta.status + ' ' + data.meta.msg) fail = (err) => @emit 'error', err helper.jsonp(uri).then(done, fail)
  11. Make Promise from the Class function api (domain) { var

    dfr = Q.defer(), blog = new Blog(domain, CONSUMER_KEY); blog.on('load', dfr.resolve); blog.on('error', dfr.reject); blog.request('photo', 0); return dfr.promise; }