Colback.js

JavaScript asynchronous paradigm shift in the blink of an eye.


There are a lot of ways to deal with asynchronous flow in JavaScript. But, even if diversity must be cherished, it is sometimes a drag to gather libraries abiding by some different asynchronous paradigms.

Colback.js aims at providing straightforward helpers to shift functions from one asynchronous paradigm to the other.

var colback = require('colback');

var shiftedFunction = colback(myFunction)
  .from(sourceParadigm)
  .to(targetParadigm);



The ominous culprit


Let's say you want to write some fairly consistent code but need to use some libraries to gather and process data in an asynchronous fashion.

You start writing your ideas down and then, it strikes you: those libraries use two different paradigms:

var library1 = require('lib1'),
    library2 = require('lib2');

// Library one uses a classical node.js asynchronous paradigm
library1.method('key', function(err, results) {

  // Library two uses promises
  library2.method(results.id).then(
    function() {
      // Everything went smoothly...
    },
    function() {
      // Something went horribly wrong...
    }
  );
});

Well, now you start to understand why the fine hussar on the top of the page looks pissed.

Rejoice however, for it is very simple, with Colback.js to get consistent again.

var library1 = require('lib1'),
    library2 = require('lib2'),
    colback = require('colback');

// Let's assume you prefer promises over standard node.js way
var shiftedFunction = colback(library1.method).from('modern').to('promise');

// Now let's use our shifted function likewise
shiftedFunction('key').then(function(results) {
  library2.method(results.id).then(
    function() {
      // Everything went smoothly...
    },
    function() {
      // Something went horribly bad...
    }
  );
});

Note that Colback.js does not aim at solving callback hell. Some fairly good libraries such as async or contra already exist for this kind of issues.



Summary




Installation


Colback.js can be used with Node.js, Phantom.js, and in the browser through Browserify.

To install with npm:

npm install colback

// To install latest development version
npm install git+https://github.com/Yomguithereal/colback.git

Then require it:

var colback = require('colback');



Asynchronous paradigms


One can find at least five main asynchronous functions' paradigms in JavaScript.

The classical paradigm

Good ol' way to deal with asynchronous flow in JavaScript.

asyncFunction(
  function(result) {
    // Everything went smoothly...
  },
  function(err) {
    // Something went horribly wrong...
  }
);

The baroque paradigm

Quite frankly, I'd wish this one not to exist at all but we can never be sure we won't step on it one day.

asyncFunction(
  function(err) {
    // Something went horribly wrong...
  },
  function(result) {
    // Everything went smoothly...
  }
);

The modern paradigm

The node.js style.

asyncFunction(function(err, result) {
  if (err)
    // Something went horribly wrong...
  else
    // Everything went smoothly...
});

The promise paradigm

The cool kids way?

asyncFunction().then(
  function(result) {
    // Everything went smoothly...
  },
  function(err) {
    // Something went horribly wrong...
  }
);

N.B.: By default, Colback.js uses then's promise implementation.

The deferred paradigm

The cool kids other way?

asyncFunction()
  .then(function(result) {
    // Everything went smoothly...
  })
  .fail(function(err) {
    // Something went horribly wrong...
  });

N.B.: By default, Colback.js uses Q's deferred implementation.



Paradigm shifting


var colback = require('colback');

var shiftedFunction = colback(originalFunction, [scope])
  .from(paradigm)
  .to(paradigm, [implementation]);

// Available paradigm, as stated before, are:
// 'classical', 'baroque', 'modern'
// 'promise' and 'deferred'

Examples

Shifting a function from the promise paradigm to the modern one:

var modernFunction = colback(promiseFunction)
  .from('promise')
  .to('modern');

Shifting a function that needs a precise scope:

// Example class
function Example() {

  this.salutation = 'Hello!';

  this.greet = function() {
    return this.salutation;
  };
}

// One would need the scope to be correct when applying this class' greeting method.
var example = new Example();

var shiftedMethod = colback(example.greet, example)
  .from('modern')
  .to('classical');

// Note that you could also do the following
var shiftedMethod = colback(example.greet.bind(example))
  .from('modern')
  .to('classical');

Using your own promise or deferred implementation rather than defaults.

var myDeferred = require('deferred');

var shiftedFunction = colback(originalFunction)
  .from('classical')
  .to('deferred', myDeferred);

Shifting a whole batch of functions at once

var originalFunctions = {
  one: function1,
  two: function2
};

var shiftedFunctions = colback(originalFunctions).from('deferred').to('classical');

// Now let's call them likewise:
shiftedFunctions.one();
shiftedFunctions.two();



What the hell is a colback?


Colbacks are a kind of hat originating from Turkey and that were mainly worn by napoleonic cavalry.

Unfortunately there is no English Wikipedia article about this fine hat. So, if you are the adventurous kind, you could be that one person willing to translate the French page. Note that if you do, I shall praise you until the end of times.

If you feel frustrated by this lack of sources but still want to quench your thirst about napoleonic headgear, have this page about shakos instead.

The phonetic proximity between "callback" and "colback" is of course strictly coincidental.



Contribution


Build Status

Contributions are more than welcome. Just remember to add and pass relevant unit tests before submitting any changes.

# Installing package dependencies
npm install

# Running tests
npm test



License


The MIT License (MIT)

Copyright (c) 2014 Guillaume Plique

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.