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.
- new / flow / with : optional chainable instantiator; receives beginning result; useful in series
- beforeAll / before : non-blocking function called once before first task
- beforeEach : non-blocking function called once before each task
- serial / series / blocking / waterfall : blocking function called in order; results always waterfalled
- parallel / nonblocking : non-blocking function called in order
- do / then / try / begin / start / auto : optionally blocking function called in order; determined by length of arguments callback expects
- afterEach / between / inbetween : non-blocking function called once after each task
- error / catch / rescue : blocking function called when error occurs
- success / else : non-blocking function called after all tasks have completed, but only if no errors occur
- end / finally / ensure / afterAll / after / complete / done / go : blocking function called after all tasks have completed
- whilst : provide test, iterator, and callback functions. will iterate until test passes, then execute callback
- delay : inverts argument order to
setTimeout()for easier CoffeeScript markup - push / nextTickGroup : serially-queued automatic-kick-start execution like
nextTick()orsetTimeout(f,0), but grouped
5 thoughtful single-chain
7 order of operations
5 escape callback hell!
Partially backward-compatible with async.js:
async.series [
->async.delay100, @->async.delay50, @
], ->assert.closeTo100+50, since(start), 25async.parallel [
->async.delay100, @->async.delay50, @
], ->assert.closeTo (100+50)+100, since(start), 25done()But better thanks to several improvements:
async
.serial((next) ->assert.typeOf next, 'function'nextnull, 'async data'# e.g., fs.readFile(), or jQuery.ajax()
)
.parallel((data, next) ->assert.equal data, 'async data'assert.typeOf next, 'function'nextnull
)
.parallel((data, next) ->assert.equal data, 'async data'assert.typeOf next, 'function'nextnull
)
.serial(->assert.typeOf@, 'function'# `this` === `next`@null, 1, 2, 3, 4, 5, 6
)
.end (err, results...) ->assert.equal err, nullassert.deepEqual results, [ 1, 2, 3, 4, 5, 6 ]
done()In fact, way better:
flow=newasyncfor i in [1..10]
((i) ->method=if i%3then'parallel'else'serial'# an overcomplicated display of flexibility
flow[method] (next) ->async.delay25, ->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=falseasyncbefore:->#loading.show()called=truedo: (next) -># main logicassert.ok called
next'err', 'result'error: (err) ->assert.equal'err', 'err'#alert errsuccess: (result) ->assertfalse, 'success() should not have been called here'#console.log datacomplete: (err, result) ->assert.equal err, 'err'assert.equal result, 'result'#loading.hide()done()Exhibit B: How about to you JavaScript developers?
called=falseasync
.try(->@newError'thrown node cb style'
)
.catch((err) ->called=trueassert.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=falseasync
.begin(->@newError'thrown node cb style'
)
.rescue((err) ->called=trueassert.equal''+err, 'Error: thrown node cb style'
)
.else((result) ->console.log'Else'assertfalse, '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()), 100async.push'B', (next) ->
setTimeout (->console.log'first'; next()), 10async.push'A', (next) ->
setTimeout (->console.log'third'; next()), 1# outputs:# first# second# thirdThese 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.
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...
i could name variables better to assist with minification but its already pretty small. i may do it later though.
potential node.js madness: each series becomes its own cpu thread, each parallel becomes its own gpu thread.
"GPUs have evolved to the point where many real-world applications are easily implemented on them and run significantly faster than on multi-core systems. Future computing architectures will be hybrid systems with parallel-core GPUs working in tandem with multi-core CPUs.' -- Professor Jack Dongarra, Director of the Innovative Computing Laboratory, The University of Tennessee