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

I love async but I can't code like this

masylum
August 09, 2012

I love async but I can't code like this

Writing javascript asynchronous programs can be a pain in the ass. I want to share some patterns that may help you.

masylum

August 09, 2012
Tweet

More Decks by masylum

Other Decks in Programming

Transcript

  1. Synchronous code evaluation 1 - function printL() { 3 -

    console.log('L'); } 2 - printL(); 4 - console.log('O'); 5 - console.log('L'); 6 - End, the event loop is empty: Exit Friday, August 10, 12
  2. Asynchronous code evaluation 1 - setTimeout(function printO() { ? -

    console.log('O'); }, Math.random * 1000); 2 - setTimeout(function printL() { ? - console.log('L'); }, Math.random * 1000); 3 - console.log('L'); 4 - End, `printL` and `printO` in the EL 7 - End, `printL` or `printO` in the EL 8 - End, the event loop is empty: Exit Friday, August 10, 12
  3. Problem? • Order may matter • Code may get evaluated

    or not • Your program is not under your control • ... you name it Friday, August 10, 12
  4. Example: Get A from db then use A.id to get

    B from db then use B.id to get C A B C Chain pattern Friday, August 10, 12
  5. Chain pattern setTimeout(function A() { console.log('A'); setTimeout(function B() { console.log('B');

    setTimeout(function C() { console.log('C'); }, 10); }, 250); }, 100); Friday, August 10, 12
  6. Imperative paradigm == How Do A, then do B, then

    you get C Friday, August 10, 12
  7. Imperative paradigm == How Example: To get an average you

    have to: Get the size of your dataset, then add your inputs and divide both results. Friday, August 10, 12
  8. Functional paradigm == Wat C is what you get from

    B once you did A Friday, August 10, 12
  9. Functional paradigm == Wat Example: An average is: What you

    get after diving your added inputs by the dataset size Friday, August 10, 12
  10. Asynchronous code is not linear, so define your problems in

    a functional way if possible. Friday, August 10, 12
  11. Chain pattern function C() { console.log('C'); } function B() {

    console.log('B'); setTimeout(C, 10); } function A() { console.log('A'); setTimeout(B, 250); } setTimeout(A, 100); Friday, August 10, 12
  12. Chain pattern var Step = require('step'); Step(function A() { console.log('A');

    setTimeout(this, 100); }, function B() { console.log('B'); setTimeout(this, 250); }, function C() { console.log('C'); setTimeout(this, 10); }); Friday, August 10, 12
  13. Chain pattern var async = require('async'); async.series([function A() { console.log('A');

    setTimeout(this, 100); }, function B() { console.log('B'); setTimeout(this, 250); }, function C() { console.log('C'); setTimeout(this, 10); }]); Friday, August 10, 12
  14. Chain pattern // I WANT A BETTER API! setTimeout(Chainer(function A()

    { console.log('A'); }), 100); setTimeout(Chainer(function B() { console.log('B'); }), 250); setTimeout(Chainer(function C() { console.log('C'); }), 10); Friday, August 10, 12
  15. Chain pattern var Chainer = function (fn) { (Chainer.functions =

    Chainer.functions || []).push(fn); return function next() { fn['arguments'] = arguments; fn.done = true; (function run() { if (Chainer.functions.length && Chainer.functions[0].done) { var el = Chainer.functions.shift(); el.apply(el, el['arguments']); run(); } }()); }; }; Friday, August 10, 12
  16. Do n asynchronous calls, process them, and trigger a callback

    once all are evaluated. Parallel pattern Friday, August 10, 12
  17. Parallel pattern var count = 2; function callback() { count--;

    if (count === 0) console.log('DONE!'); } setTimeout(function A() { console.log('A'); callback(); }, 100); setTimeout(function B() { console.log('B'); callback(); }, 250); Friday, August 10, 12
  18. Parallel pattern Step(function parallel() { var self = this; setTimeout(function

    A() { console.log(’A’); self.parallel(); // FFFUUU API }, 100); setTimeout(function B() { console.log(’B’); self.parallel(); // FFFUUU API }, 250); }, function callback() { console.log('DONE'); }); Friday, August 10, 12
  19. Parallel pattern async.parallel([function(){ setTimeout(function A(callback) { console.log(’A’); callback(); }, 100);

    setTimeout(function B(callback) { console.log(’B’); callback(); }, 250); }], function callback() { console.log('DONE'); }); Friday, August 10, 12
  20. Parallel pattern setTimeout(parallel(function A() { console.log('A'); }), 100); setTimeout(parallel(function B()

    { console.log('B'); }), 250); parallel.callback = function () { console.log('DONE!'); }; Friday, August 10, 12
  21. Parallel pattern var parallel = function () { var count

    = 0; return function parallel(fn) { count++; fn = fn || function () {}; return function () { fn.apply(fn, arguments); if (!--count) { parallel.callback(); } }; }; }; Friday, August 10, 12
  22. Use named functions, always. Try to create the API you

    need. Handle errors always. Think functional! My advice Friday, August 10, 12