JSPM

  • Created
  • Published
  • Downloads 231
  • Score
    100M100P100Q81874F

The simplest way to manage callbacks.

Package Exports

  • do

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (do) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

"do" is the simplest way to manage callbacks.

If you don't want to use all the async/chain libraries but just want a reliable way to know when the function is done - this is for you.

Installation

npm i do

Usage

You need to specify "error" + "success" or "complete" callback, otherwise "Do" will throw an error.

var Do = require('do');
var todo = Do(1);
// use success and error callbacks
todo.error();
todo.success(success);
// or use complete callback
todo.complete(function() {
    console.log(this.errors);
});
todo.done();

Api

Do()

Do constructor.

Examples:

// Create 1 todo
var todo = new Do();
// Create 3 todos.
var todo = new Do(3);
// Without a "new" statement.
var todo = Do();

Do#amount(value:Number?)

Setter/getter for amount of todos.

Examples:

// Get the current amount.
todo.amount();
// Set a new amount.
todo.amount(3);

Do#inc(value:Number?)

Increment amount of todos.

Examles:

// Add 1 todo.
todo.inc();
// Add 3 todos.
todo.inc(3)

Do#dec(value:Number?)

Decrement amount of todos.

Examples:

// Reduce at 1 todo.
todo.dec();
// Reduce at 3 todos.
todo.dec(3)

Do#error(err:Function|Error?)

Set an error callback or trigger an error.

Error callback is called EVERY time an error is passed to Do#done or Do#error. If you send an http response inside of the error handler, ensure to do it only once or use complete callback.

Examples:

// Define error callback.
var send;
todo.error(function(err) {
    console.error(err);
    // Ensure sending response only once.
    if (!send) {
       req.send('Error');
       send = true;
    }
});
// Trigger an error manually.
todo.error(new Error());

Do#success(fn:Function?)

Set a success callback or trigger success.

If all todos are done without errors - success callback will be called by Do#done. Success callback is called ONLY ONCE.

Examples:

// Define a success callback.
todo.success(function() {
   res.send('Success');
});
// Trigger success manually.
todo.success();

Do#complete(fn:Function?)

Set a complete callback or trigger complete.

Complete callback is always called ONCE if it is defined independent of errors.

Examples:

// Define a complete callback.
todo.complete(function() {
   console.error(this.errors);
   res.send('Complete');
});
// Trigger complete manually.
todo.complete();

Do#done(err:Error?)

Indicate a done task. If an error is passed as first parameter - error will be triggered.

Examples:

// with error
todo.done(err);
// without error
todo.done();
// context of `todo.done` is ensured.
someTask(todo.done);

Also it solves another issue with callbacks. If we pass a function reference to some other function - we never know if the other function could call the callback synchronously f.e. in case there is nothing todo in async manner. In that case and in case of conditional incrementation/decrementation of todos amount, it can happen that Do#done is called more than once.

Example:

var todo = Do();
todo.error(error);
todo.success(success);
function someAyncFn(callback) {
   if (nothingTodo) {
       return callback();
   }
}
if (a == 1) {
    todo.inc();
    // If this function calls `done` callback synchronously - success callback
    // will be called as there is nothing to do any more and the case "a == 2"
    // is not executed yet.
    someAyncFn(todo.done);
}
if (a == 2) {
    todo.inc();
    someAyncFn(todo.done);
}

Examples

Mix parallel and serial executions

var Do = require('do'),
    todo = new Do(2);

todo.error(errorHandler);
todo.success(successHandler);

function parallelTask1(callback) {
    function serialTask1() {
        var todo = new Do(2);
        todo.error(callback);
        todo.success(serialTask2);
        parallelTask1(todo.done);
        parallelTask2(todo.done);
    }

    function serialTask2() {
        var todo = new Do(2);
        todo.error(callback);
        todo.success(callback);
        parallelTask1(todo.done);
        parallelTask2(todo.done);
    }

    serialTask1();
}

function parallelTask2(callback) {
    function serialTask1() {
        var todo = new Do(2);
        todo.error(callback);
        todo.success(serialTask2);
        parallelTask1(todo.done);
        parallelTask2(todo.done);
    }

    function serialTask2() {
        var todo = new Do(2);
        todo.error(callback);
        todo.success(callback);
        parallelTask1(todo.done);
        parallelTask2(todo.done);
    }

    serialTask1();
}

parallelTask1(todo.done);
parallelTask2(todo.done);

Express application

var Do = require('do');

app.post('/', function(req, res, next) {
    var todo = new Do(3);

    // If an error happens, next callback will be called and the error passed along.
    todo.error(next);

    // If everything is done and no errors happened, success callback is called.
    todo.success(function() {
        res.send({status: 'ok'});
    });

    db.fetch(userId, function(err, user) {
        if (err) return todo.done(err);

        update(user, todo.done);
        notify(user, todo.done);
        addSomeBackgroundTask(user, todo.done);

        if (userId == '123456') {
            todo.inc();
            specialTaskForTheUser(user, todo.done);
        }

        if (user.type == 'freak') {
            todo.inc(3);
            task1(user, todo.done);
            task2(user, todo.done);
            task3(user, todo.done);
        }
    });
});

Run tests

npm test

Licence

MIT