Better async utilities for node and the browser


Keywords
async, asynchronous, flow, control, library, node.js, node, javascript, better, minimalist, improved, alternative
License
MIT
Install
npm install async2@0.1.9

Documentation

Async2.js

Better asynchronous javascript flow control in 132 lines (5.7KB) or 4KB minified or 1285 bytes gzipped.

Inspired by async, mini-async, Mocha, Chai, Should.js, and IcedCoffeeScript/TameJs libraries.

Flow Control

Quick Examples

First, reflect upon our haiku mantra:

5  thoughtful single-chain
7  order of operations
5  escape callback hell!

Then, observe in action:

Partially backward-compatible with async.js:

async.series [
 -> async.delay 100, @
 -> async.delay 50, @
], ->
  assert.closeTo 100+50, since(start), 25

  async.parallel [
   -> async.delay 100, @
   -> async.delay 50, @
  ], ->
    assert.closeTo (100+50)+100, since(start), 25
    done()

But better thanks to several improvements:

async
  .serial((next) ->
    assert.typeOf next, 'function'
    next null, 'async data' # e.g., fs.readFile(), or jQuery.ajax()
  )
  .parallel((data, next) ->
    assert.equal data, 'async data'
    assert.typeOf next, 'function'
    next null
  )
  .parallel((data, next) ->
    assert.equal data, 'async data'
    assert.typeOf next, 'function'
    next null
  )
  .serial(->
    assert.typeOf @, 'function' # `this` === `next`
    @ null, 1, 2, 3, 4, 5, 6
  )
  .end (err, results...) ->
    assert.equal err, null
    assert.deepEqual results, [ 1, 2, 3, 4, 5, 6 ]
    done()

In fact, way better:

flow = new async
for i in [1..10]
  ((i) ->
    method = if i%3 then 'parallel' else 'serial' # an overcomplicated display of flexibility
    flow[method] (next) ->
      async.delay 25, ->
        console.log "#{method} #{i}"
        next()
  )(i)
flow.go (err, results...) ->
  console.log 'try this in async.js!'
  done()

It really makes you wonder: how long have we needed a good asynchronous flow control library, and not known it?

Exhibit A: Look familiar to any jQuery.ajax() developers?

called = false
async
  before: ->
    #loading.show()
    called = true
  do: (next) ->
    # main logic
    assert.ok called
    next 'err', 'result'
  error: (err) ->
    assert.equal 'err', 'err'
    #alert err
  success: (result) ->
    assert false, 'success() should not have been called here'
    #console.log data
  complete: (err, result) ->
    assert.equal err, 'err'
    assert.equal result, 'result'
    #loading.hide()
    done()

Exhibit B: How about to you JavaScript developers?

called = false
async
  .try(->
    @ new Error 'thrown node cb style'
  )
  .catch((err) ->
    called = true
    assert.equal ''+err, 'Error: thrown node cb style'
  )
  .finally (err, result) ->
    assert.ok called
    assert.equal ''+err, 'Error: thrown node cb style'
    assert.typeOf result, 'undefined'
    done()

Exhibit C: Any Rubists in the audience?

called = false
async
  .begin(->
    @ new Error 'thrown node cb style'
  )
  .rescue((err) ->
    called = true
    assert.equal ''+err, 'Error: thrown node cb style'
  )
  .else((result) ->
    console.log 'Else'
    assert false, 'else() should not have been called here'
  )
  .ensure (err, result) ->
    assert.ok called
    assert.equal ''+err, 'Error: thrown node cb style'
    assert.typeOf result, 'undefined'
    done()

Additionally, nextTick() users will appreciate the lazy man's grouped blocking serial execution:

async.push 'A', (next) ->
  setTimeout (-> console.log 'second'; next()), 100
async.push 'B', (next) ->
  setTimeout (-> console.log 'first'; next()), 10
async.push 'A', (next) ->
  setTimeout (-> console.log 'third'; next()), 1
# outputs:
# first
# second
# third

These are just a few of all the things it can do.

For the latest examples, review the easy-to-follow ./test/test.coffee.

Or try it immediately in your browser with codepen.

FAQ

  • great another high horsed coffeescripter! i just prefer to author in coffee. the .js and .js.min versions are in here too. you can do all the same things; in fact it is partially backward-compatible with async.js but in less lines of .js less bytes i should say; its a minimalist implementation with some improvements.

  • have you tried pull requests to the async repo? i may if i get positive response but its 100% refactor from ground-up; its not just a pull request. also any snide remarks are meant to encourage spirited but constructive debate. i'm not trying to be divisive. just had a need with a short timeline :) i know a lot of people get used to the way things are...