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

Web app with functional programming

Web app with functional programming

15f492c0208722911c8225f31f2671be?s=128

Yu I.

June 27, 2014
Tweet

Transcript

  1. Web app with functional programming

  2. Motivation

  3. grunt-browserify is now super cool!

  4. Functional programming seems super cool!

  5. None
  6. http://japboy.github.io/slidr

  7. 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
  8. 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!
  9. Underscore as functional toolchain » Very useful in case to

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

    to be functional » Q is portable Promise implementation for client- and server-sides
  11. Q is great if functions are idempotent

  12. Idempotent?

  13. Idempotent function f (a, b) { return a + b;

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

    return a + b + x; } f(1, 2); // => 4 Result depends on the value of x
  15. 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; }
  16. 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!
  17. Reuse of chaining Promises function show () { submit() //

    Repeated process .then(api) .then(cache) .then(show); } Easy to build them up again!
  18. Wrap anything that are complicated

  19. Complicated?

  20. 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)
  21. 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; }
  22. Create small parts and build them up!

  23. Functional is fun!