# Asynchronous DSL for CoffeeScript serial = (f) -> next = -> arr.shift().apply(null, arguments) if arr.length arr = (v for k, v of f(next)) next() null parallel = (f, after = ->) -> res = {}; arrc = 0 arrc++ for k, v of f for k, v of f do (k, v) -> v (args...) -> res[k] = args if not --arrc then after(res) null ######################### # serial test w/ mock fs fs = open: (_, _, cb) -> console.log('[fs.open]'); cb(0, {a_fake: 'file object'}) write: (f, _, cb) -> console.log('[fs.write]', f); cb(0, f) close: (f, cb) -> console.log('[fs.close]', f); cb(0, f) # serial accepts a function with one "next" continuation, # which returns a list of steps to execute in order # you can label your steps anything, but numbers look good: serial (next) -> 1: -> fs.open('file', 'w', next) 2: (err, f) -> fs.write(f, 'Apples', (a...) -> next(a..., f)) 3: (err, written, f) -> fs.close(f, next) last: -> console.log 'Serial test complete.' ############################## # parallel test with timeouts console.log('Waiting for parallel test...') # parallel accepts a list of steps to execute in any order # (each step is passed a "done" continuation to call when finished) # and an (optional) last function to call with results of each step parallel A: (done) -> setTimeout((-> done(new Date)), 1000) B: (done) -> setTimeout((-> done(new Date)), 3000) C: (done) -> setTimeout((-> done(new Date)), 2000) (res) -> console.log 'Parallel results:', JSON.stringify(res)