Async.js for Q

Promises with Q are awesome. However,
there's a lot of existing code done using callback-oriented structures.
Much of this probably would have collapsed under its own weight long ago were
it not for the excellent async.js.

A number of the functions provided by async.js, e.g. parallel() aren't
terribly useful to existing Q users, since you can just call Q.all(), but
I've included most of the functions for completeness.

All of the functions which return promises can also accept promises as any of
their arguments, for example instead of:

Arguments

worker(task) - An promise-returning function for processing a queued
task, which must resolve its promise when finished.

concurrency - An integer for determining how many worker functions should be
run in parallel.

Queue objects

The queue object returned by this function is an EventEmitter:

Functions

length() - a function returning the number of items waiting to be processed.

push(task) - add a new task to the queue and return a promise which is
resolved once the worker has finished processing the task. The promise
object returned also contains a start property, which is a promise which
is resolved when the task is started.
Instead of a single task, an array of tasks can be submitted and an array
of promises will be returned which can be individually handled or bundled
with Q.all()

unshift(task) - same as push but add a new task to the front of the queue.

Properties

concurrency - an integer for determining how many worker functions should be
run in parallel. This property can be changed after a queue is created to
alter the concurrency on-the-fly.

Events

You may receive events with queueObj.on 'foo', -> ...

saturated - emitted when the queue length hits the concurrency and further
tasks will be queued

empty - emitted when the last item from the queue is given to a worker

drain - emitted when the last item from the queue has returned from the worker
NOTE: actions contigent on the promise returned from the
push/unshift() that queued the final task will not have finished
when the drain event is fired; if you wish to run after that,
do something like: queueObj.on 'drain', -> process.nextTick -> ...
or use a Q.all(...).then(...) on those promises instead.

Arguments

worker(tasks) - A promise-returning function for processing an array of
queued tasks.

payload - An optional integer for determining how many tasks should be
processed per round; if omitted, the default is unlimited.

Cargo objects

The cargo object returned by this function is an EventEmitter:

Functions

length() - a function returning the number of items waiting to be processed.

push(task) - add a new task to the queue, returns a promise that is resolved
once the worker has finished processing the task.
Instead of a single task, an array of tasks can be submitted in which case
an array of promises will be returned.

Properties

payload - an integer for determining how many tasks should be
process per round. This property can be changed after a cargo is created to
alter the payload on-the-fly.

Events

You may receive events with cargoObj.on 'foo', -> ...

saturated - emitted when the queue length hits the payload and further
tasks will be queued

empty - emitted when the last item from the queue is given to a worker

drain - emitted when the last item from the queue has returned from the worker
NOTE: actions contigent on the promise returned from the
push() that queued the final task will not have finished
when the drain event is fired; if you wish to run after that,
do something like: cargoObj.on 'drain', -> process.nextTick -> ...
or use a Q.all(...).then(...) on those promises instead.