Slide 1

Slide 1 text

Web app with functional programming

Slide 2

Slide 2 text

Motivation

Slide 3

Slide 3 text

grunt-browserify is now super cool!

Slide 4

Slide 4 text

Functional programming seems super cool!

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

http://japboy.github.io/slidr

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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!

Slide 9

Slide 9 text

Underscore as functional toolchain » Very useful in case to read JSONs from ReST APIs » "Functional JavaScript" says Underscore is promising to be functional

Slide 10

Slide 10 text

Q as Promise object » Asynchronous process needs any wrapper to be functional » Q is portable Promise implementation for client- and server-sides

Slide 11

Slide 11 text

Q is great if functions are idempotent

Slide 12

Slide 12 text

Idempotent?

Slide 13

Slide 13 text

Idempotent function f (a, b) { return a + b; } f(1, 2); // => 3 Same result as always!

Slide 14

Slide 14 text

Changed var x = 1; function f (a, b) { return a + b + x; } f(1, 2); // => 4 Result depends on the value of x

Slide 15

Slide 15 text

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; }

Slide 16

Slide 16 text

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!

Slide 17

Slide 17 text

Reuse of chaining Promises function show () { submit() // Repeated process .then(api) .then(cache) .then(show); } Easy to build them up again!

Slide 18

Slide 18 text

Wrap anything that are complicated

Slide 19

Slide 19 text

Complicated?

Slide 20

Slide 20 text

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)

Slide 21

Slide 21 text

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; }

Slide 22

Slide 22 text

Create small parts and build them up!

Slide 23

Slide 23 text

Functional is fun!