Thursday, February 14, 2013

Async Javascript (notes for a great book)

Martin Fowler recommended Trevor Burnham’s Async JavaScript: Build More Responsive Apps with Less Code. I was interested on the topic and picked the book and I was pretty satisfied with the book. Async JS concepts were opened in a clear way at a proper level for me.

Bunch of notes (mostly for myself) follow:

Understanding Javascript Events

  • Javascript thread & event model : single thread & Event Queue
    • Note that JS was selected for Node.js because JS being a great fit for nonblocking I/O
  • Event sources : I/O & timing functions
  • Async function : A function that can cause another function (callback) to run later from the event queue
    • Note that in some cases a function is async only sometimes
  • Misc advices:
    • Async recursion considered as an anti-pattern.
    • Never define a potentially synchronous function that returns a value that could be useful for the callback.
    • Read the source code for the functions you use.
    • Avoid nesting many levels of callbacks.

Distributing Events

  • PubSub : distributed events (single incident might cause reactions through the whole application)
  • Evented Models (Backbone, Ember.js)
  • Note that PubSub isn’t inherently async in itself

Promises/Deferreds

In brief : A Promise is an object that represents a task with two possible results (success & failure) and holds callbacks when one or other outcome has occurred

  • Pros :
    • encapsulation
    • possibility to pass a promise around
    • possibility to derive new promises from existing ones
  • Two major alternatives
  • Deferred : superset of Promise with addition : one can trigger a Deferred straight
  • Promise combinations etc
    • $.when : “logical AND
    • piping
  • jQuery callbacks : done, fail, always, progress
  • More and more JS libraries will probably start to return promises. Until then, one can easily convert async functions to Promise generator

Node-style promise generation from a callback:

var reading = $.Deferred();
fs.readFile(filename, 'utf8', function(err) {
  if(err) {
    reading.reject(err);
  } else {
    reading.resolve(Array.prototype.slice.call(arguments, 1);
  }
}

Flow control with Async.js

  • Similarly as Underscore.js can help synchronous iterative code, a flow control library (as Async.js) can help async code.
  • Collection methods:
    • async.filter, async.forEach (parallel)
    • async.filterSeries, async.forEachSeries (sequentially)
    • also other “main functional iteration methods”
  • Task organization:
    • async.series (one task at the same time)
    • async.parallel (all tasks at the same time)
    • async.queue (n tasks at the same time)
  • Lightweight alternative Step

Workers

  • JavaScript is single-thread by nature
  • Web Workers “part of HTML5“, one can run code in multiple threads
    • Inter-process communication with events
      • through Event Queue
      • data copied & “serialized+deserialized”
    • Not supported with all major browsers (yet)
  • Node Workers with cluster

Async script loading

  • script tag is blocking
    • browser will continue to read the document and download resources but won’t evaluate them until the script has been downloaded and run
    • script in the head → nothing shown before script is downloaded and run
    • thus scripts often moved to end of body, unless
      • script might be called from inlin
      • browser-enhancing script like Modernizr
      • script affecting how rendered page looks like
  • defer
    • “start loading the script right away but don’t run it before document is ready and previous defer scripts are run
  • async
    • “load & run scripts as soon as possible”
    • for independent scripts only
  • Programmatic loading
    • yepnope : very lightweight way
    • Require.js & AMD : for applications with complex script dependencies

Misc links: