$30 off During Our Annual Pro Sale. View Details »

Callbacks are calling back

Callbacks are calling back

Nested callbacks get really cumbersome after a while. Let's see some alternatives for a better Future of JS.
I Promise it will make your js code nicer.

Bruno Lara Tavares

April 24, 2013
Tweet

More Decks by Bruno Lara Tavares

Other Decks in Programming

Transcript

  1. Callbacks are calling
    back!

    View Slide

  2. Anatomy of a callback

    View Slide

  3. var $as = $(“a”);!
    !
    $as.on(“click”, function(e) {!
    /* do some stuff now that click
    happened */!
    });!

    View Slide

  4. NodeJS: Evented IO

    View Slide

  5. Evented IO + CPS
    •  Processes happens as events happens
    – Waiting for a result is not feasible
    •  Continuing the process in the future
    –  Passing it to future processes

    View Slide

  6. Now we know the reasons to
    use a callback…
    Let’s see some different
    approaches to deal with future
    data

    View Slide

  7. Futures
    •  Deferred process handling
    var data = Future(function (handler) { /*
    do http request */ });!
    !
    handleUserInterface();!
    putValuesOnTheFields(data.getValue()); !

    View Slide

  8. Broken implementation
    function Future(p) {!
    var value, finished;!
    finished = false;!
    process.nextTick(function() { p(function(result) { !
    " "value = result;!
    " "finished = true; })});!
    !
    return { !
    getValue: function getValue() { !
    if(!finished) {!
    console.log("not ready");!
    arguments.callee();!
    }!
    return value;!
    }!
    }!
    };!
    !
    !
    var p = Future(function(end) { setTimeout(function() { end(3); }, 1000) });!
    p.getValue()!
    !

    View Slide

  9. Working implementation of Future
    •  Async I/O + lack of threads makes it really
    complicated to use while loops in
    Javascript with background processes
    http://code.activestate.com/recipes/
    84317/

    View Slide

  10. Promises
    •  They are similar to Futures, in the sense
    of deferring execution.
    •  The interface allows you to create utility
    functions to combine and chain multiple
    promises
    •  (Shhhh! Promises are monads.)

    View Slide

  11. JQuery 1.5 ajax object
    var req = $.get('foo.htm');!
    !
    req.done(function(response) {!
    // do something with the response!
    });!
    !
    req.fail(function() {!
    // do something if the request failed!
    });!
    !
    var lis = $(“li”);!
    req.done(function(response) {!
    // do more stuff with response and lis!
    })!

    View Slide

  12. Javascript community current state
    •  Node introduced the default api of:
    func(args…,callback(err,arrgs…))!
    !
    •  Some libraries are handling the
    implementations of Promises
    •  They got into an agreement called Promises/
    A+
    –  http://promises-aplus.github.io/promises-spec/

    View Slide

  13. Promises/A+  
    •  General
    – A promise represents a value that may not be
    available yet. The primary method for
    interacting with a promise is its then method.

    View Slide

  14. Example of a Promise
    implementation
    https://github.com/tildeio/rsvp.js/blob/
    master/lib/rsvp/promise.js

    View Slide

  15. Ok… So how can promises improve
    my code?
    Lets see some code then.

    View Slide

  16. Some context on Promises utilities
    •  We are going to show some code use the Q library
    https://github.com/kriskowal/q
    •  Q.nfbind :: (err -> result -> ()) -> Promise
    result!
    •  Q.all :: [Promise] -> Promise [Promise]!
    •  Q.spread :: [Promise] -> Promise args… -> Promise!
    •  This is not the exactly type signature, nor Haskell syntax, it is
    just similar!

    View Slide

  17. Some context on the code
    var render = console.log;!
    !
    var handleError = function(error) {!
    console.log("error");!
    console.log(error);!
    } !
    !
    var User = {};!
    User.find = function(id, callback) {!
    setTimeout(function() { !
    "callback(Math.random() < 0.1, {id: id}); !
    }, 1000);!
    }!

    View Slide

  18. var Fight = {};!
    Fight.calculateResult = function(user1, user2,
    callback) {!
    setTimeout(function() {!
    "callback(Math.random() < 0.1, {!
    " " " " " winner: user1,!
    " " " " " loser: user2 }) }!
    ,1000);!
    }!
    !
    Fight.save = function(fight, callback) {!
    setTimeout(function() { !
    "callback(Math.random() < 0.1, {!
    " " " " " "id: Math.random() * 100}) }!
    ,1000);!
    }!

    View Slide

  19. Callback style
    render("started")!
    User.find(1, function(err, user) {!
    if(err) { handleError(err); return; }!
    !
    User.find(2, function(err2, user2) {!
    if(err2) { handleError(err2); return; }!
    !
    Fight.calculateResult(user, user2, function(err3, fight){!
    if(err3) { handleError(err3); return; }!
    !
    Fight.save(fight, function(err4, fight2){!
    if(err4) { handleError(err4); return; }!
    !
    render(fight2);!
    });!
    });!
    });!
    })!
    render("ended")!
    !

    View Slide

  20. Promise style
    var Q = require("q")!
    var toPromise = Q.nfbind;!
    !
    var userFind = toPromise(User.find);!
    var fightCalculateResult = toPromise(Fight.calculateResult);!
    var fightSave = toPromise(Fight.save);!
    !
    render("started")!
    !
    Q.all([userFind(1), userFind(2)])!
    .spread(fightCalculateResult)!
    .then(fightSave)!
    .then(render)!
    .fail(handleError)!
    !
    render("ended")!

    View Slide

  21. Things I think it is important to say
    •  Expose api’s that uses the community style guide
    to maximize integration
    –  Expose func(args…, callback(err, arrgs…))!
    •  Use Promises internally to make future data
    interaction and flow more explicit
    •  Use callbacks when it makes sense (ie: click
    events…)
    •  Everything in excess is bad
    •  Try more functional approaches (:

    View Slide

  22. Things  you  think  are  important  to  say  

    View Slide

  23. Thanks!
     [email protected]  
    GitHub
    Twitter

    View Slide

  24. Links
    •  http://userserve-ak.last.fm/serve/_/63480291/Back+to+the+Future
    +ChristopherLloydBacktotheFutur.jpg
    •  http://us.123rf.com/400wm/400/400/luislouro/luislouro0912/
    luislouro091200086/6033163-businessman-back-making-a-call-by-
    cellphone-isolated-in-a-white-background.jpg
    •  http://i.qkme.me/3tdh8v.jpg
    •  https://encrypted-tbn3.gstatic.com/images?
    q=tbn:ANd9GcSMW5X93wxdF_3qmNLFCWFSHkDEmTmGr_8KTFzgTK_TOl
    Dm3NU4

    View Slide