profess

nodejs promise pattern implementation for easy async programming

npm install profess
8 downloads in the last week
20 downloads in the last month

What's profess?

Profess is a nodejs promise pattern implementation for easy async programming.

Why profess?

A lot of modules provide powerful features to deal with async programming (async, Step, Futures, node-promise to mention some of them...).

The goal of Profess is to provide an alternative solution as close as possible to the original promise idea :

  • provide a light node module (not browser code)
  • return an object with a 'then' method to chain a flow
  • does not need an array to have the all flow defined
  • prefer to use a Profess instance instead of 'this' in flow steps

What is a promise?

CommonJS Promises/A

Usage

Simple async example :

    var Profess = require('Profess');
      , profess;

    // Emulate an asynchronous process for demo purpose
    function doAsync(callback) {
      setTimeout(function () {
        callback('hello');
      }, 500);
    }

    profess = new Profess(); // Instanciate Profess class
    profess
      .do(doAsync(profess.next)) // First step : do something asynchronous, returns a Promise instance
      .then(function (value) { // the Promise instance provides the 'then' method called when the 1st step is done
        console.log(value);
      });

Error handling :

    var Profess = require('Profess')
      , fs = require('fs')
      , profess;

    profess = new Profess();
    profess
      .do(function () {
        fs.readFile(__filename, function (err, data) {
          err && profess.error(err) || profess.next(data.toString());
        });
      })
      .then(function (data) {
        console.log('data :', data);
      }, function (err) {
        // The 'then' method of Promise class provides an
        // optionnal 2nd argument callback to handle errors
        console.error(err);
      });
      // Note that if no error callback is provided,
      // promise will try to find one in next steps.
      // If none is found, promise will throw an Error.

Loop example :

    var Profess = require('Profess')
      , path = require('path')
      , fs = require('fs')
      , profess;

    function errorHandler(err) {
      console.error(err);
    }

    profess = new Profess();
    profess
      .do(function () {
        fs.readdir(__dirname, function (err, files) {
          err && profess.error(err) || profess.next(files);
        });
      })
      .then(function (files) {
        Profess.each(files, function (file, next) { // Profess class provides a 'each' helper to deal with loops
            fs.lstat(path.join(__dirname, file), function (err, stat) {
              if (err) return errorHandler(err);
              console.log('%s is a file : %s', file, stat.isFile());
              next();
            });
          },
          profess.next);
      }, errorHandler);

Loop in serie :

    var Profess = require('Profess')
      , result;

    function errorHandler(err) {
      console.error(err);
    }

    result = '';
    Profess.each([1, 2, 3],
      function (value, next) {
        setTimeout(function () {
          result += value;
          next();
        }, Math.floor(Math.random() * 100) + 1);
      }, function () {
        // result should be '123'
      });

Loop in parallel :

    var Profess = require('Profess')
      , result;

    function errorHandler(err) {
      console.error(err);
    }

    result = '';
    Profess.eachAsync([1, 2, 3],
      function (value, next) {
        setTimeout(function () {
          result += value;
          next();
        }, Math.floor(Math.random() * 100) + 1);
      }, function () {
        // result should be '123' or '132' or '213' or '231' or '321' or '312'
      });

Other helpers :

    // doAsync helper provides an alias for process.nextTick or setImmediate (depending on the node version)
    Profess.doAsync(function(){
      console.log('hello!');
    });

    // asyncFunc helper returns a function that will execute asynchronously the specified process
    var func = Profess.asyncFunc(function(){
      console.log('hello!');
    });
    func(); // executes the process

Global error handling :

    var Profess = require('Profess')
      , profess;

    // This method execute the callback once with a result, and the second time with an error
    // The goal is to simulate an async process that returns an error
    function asyncErrorGenerator(callback) {
      if (errorCounter++ % 2) {
        Profess.doAsync(function () {
          callback(error)
        });
      } else {
        Profess.doAsync(function () {
          callback(null, true)
        });
      }
    }

    function errorHandler(err) {
      // This function will be called when an error is returned at any step
      completed = true;
    }

    profess = new Profess();
    profess.
      do(function () {
        asyncErrorGenerator(profess.handleError(errorHandler));
        // First time, everything is ok
      }).
      then(function (data) {
        // data should be true
        asyncErrorGenerator(profess.handleError(errorHandler));
        // Second time, an error is returned
      }).
      then(function (data) {
        // This will never been called because of previous error
      });

Enjoy !

npm loves you