fasync

Fizker Inc async lib

npm install fasync
1 downloads in the last week
1 downloads in the last month

Fizker Inc async lib

This is a small lib that adds a couple of async helpers for javascript programming.

It is targetted at Node.js, but support for browsers will be added at some point.

Running the tests

The tests are written in jasmine, and expects Node.js as the environment. They can be run with the runTests script, as long as jasmine-node is present on the path.

Functions

  • pool()

    Creates a pool, which allows registering an arbitrary number of callbacks. It makes it simple to ensure that any number of asyncronous tasks are all complete before continuing.

    Public functions:

    • register([callback])

      Fills the pool with more content, and returns a function. Calling that function drains the pool, and the passed callback will then be called, passing all arguments as-is.

      If the first parameter of the call is not falsy, it will be assumed to be an error, and the error event will be emitted. This will throw an exception, if no error-listeners are added.

    • on(event, callback)

      Registers a listener for the given event. This will be called every time the event is triggered for the rest of the lifetime.

    • once(event, callback)

      Registers a listener for the given event. This will only be raised once for the given event.

    • whenEmpty(callback)

      Synonymous with on('empty', callback)

    It can emit the following events:

    • empty: Called when the pool is drained.
    • error: Called when any callback gives an error as the first parameter.
  • queue(worker)

    queue allows for a simple queue. It makes it easy to ensure that inherently asyncronous tasks are still performed in order.

    It takes a worker function as the single parameter, and will throw if this is not the case. The worker will always be passed two parameters:

    1. An options object, which will come as-is from the push-call.
    2. A resume callback, which will tell the queue to start the next task.

    The returned queue has the following functions:

    • push([options][, callback])

      push adds a new task to the queue. This will be executed immediately, or when the current task is completed.

      It takes two optional arguments.

      1. The first will be passed as-is to the worker, and can be used to pass along any options.
      2. The other is a callback, which will be called when the task is completed.

        If the task reports any error, this callback will be called with the error as well.

        Any errors reported by a task will break the queue, and emit the error event.

    • on(event, callback)

      Registers a listener for the given event. This will be called every time the event is triggered for the rest of the lifetime.

    • once(event, callback)

      Registers a listener for the given event. This will only be raised once for the given event.

    It can emit the following events:

    • empty: Called when the queue is empty.
    • error: Called when any callback gives an error as the first parameter.
  • waterfall(functions[, args][, callback])

    Creates a waterfall, which takes a list of functions. Each function is called in order with a resume-callback as the last parameter, and any parameters passed to the callback will be used for the next call.

    The args parameter is an optional list of arguments for the first call. If the last parameter is a function, it will be used to notify when the last function has been called.

    All functions will have a resume callback as the last parameter passed to it. The waterfall will pause its cascade until resume is called.

    The other parameters depend on one of two things:

    1. The first function will get the other parameters from the args parameter.
    2. The other functions will get the parameters passed to resume, minus the first.

    If the first parameter to resume is truthy, it will be considered an error, and the waterfall will stop cascading.

    When an error occurs or the last function is called, the initial callback will be called with any arguments passed by the last function called.

Code examples

Pool

The following example shows how to read a list of files asyncronously, and concatenate them when they are all read.

var async = require('fasync'),
    pool = async.pool(),
    fs = require('fs'),
    files = [
        'a.txt',
        'b.txt',
        'c.txt'
    ];

pool.on('empty', function() {
    fs.writeFile('out.txt', files.join('\n'));
    console.log('pool is drained');
});

files.forEach(function(file, i) {
    fs.readFile(pool.register(function(err, content) {
        if(err) {
            return;
        }

        files[i] = content.toString();
    }));
});

Queue

The following example re-implements the pool-example using the queue.

var async = require('fasync'),
    queue = async.queue(worker),
    fs = require('fs'),
    files = [];

queue.on('empty', function() {
    fs.writeFile('out.txt', files.join('\n'));
    console.log('queue is empty');
});

queue.push('a.txt');
queue.push('b.txt');
queue.push('c.txt');

function worker(file, resume) {
    fs.readFile(function(err, content) {
        if(!err) {
            files.push(content.toString());
        }
        resume(err);
    });
};

Waterfall

The following example will read the file in.txt, convert it to JSON, check against a value, and write it to out.txt.

If the file contains a specific key, it will raise an error, which will break the callstack prematurely. Any errors on the file-operations will likewise cause it to break.

var async = require('fasync'),
    fs = require('fs');

async.waterfall([
    fs.readFile,
    parseContents,
    fs.writeFile
], [ 'in.txt' ], onComplete);

function parseContents(content, resume) {
    var data = JSON.parse(content.toString());
    if(data.someKey == 'some value') {
        resume('Error state');
        return;
    }
    data.someKey = 'some new value';
    resume(null, 'out.txt', JSON.stringify(data));
}

function onComplete(err) {
    if(err) {
        console.error(err);
        process.exit(1);
    }
}
npm loves you