node package manager
Easy sharing. Manage teams and permissions with one click. Create a free org »

chainit

chainit Build Status Dependency Status devDependency Status

Selenium Test Status

Turn an asynchronous JavaScript api into an asynchronous chainable JavaScript api.

usage

function MyApi() {}
MyApi.prototype.method1 = function(cb) {cb()}
MyApi.prototype.method2 = function(cb) {cb()}
 
var chainit = require('chainit');
var MyChainApi = chainit(MyApi);
var obj = new MyChainApi();
obj
  .method1()                      // 1st call 
  .method2()                      // 2nd call 
  .method1(function(/* args */) { // 3rd call 
    this.method1();               // 4th call 
  })
  .method2();                     // 5th call 

Adding or overriding methods

Adding and overriding methods works at both prototype level and instance level.

You must use chainit.add(chain, methodName, method), you can't do direct assignation (chain.methodName = method) because object.observe is not yet ready.

function MyApi() {}
MyApi.prototype.method1 = function(cb) {cb()}
MyApi.prototype.method2 = function(cb) {cb()}
 
var chainit = require('chainit');
var MyChainApi = chainit(MyApi);
 
var obj = new MyChainApi();
 
// override instance method 
chainit.add(obj, 'method1', function(cb) {
  cb()
});
 
obj
  .method1() // calls the newly added method1 
  .method2();
 
// revert original method 
chainit.add(obj, 'method1', MyApi.prototype.method1);
 
// override prototype method 
chainit.add(MyChainApi, 'method1', function(cb) {
  cb()
});
 
var obj2 = new MyChainApi();
 
obj2.method1(); // calls the newly chained prototype `method1` 

features

Features:

  • supports async apis
  • supports (crazy) nested calls
  • supports static and prototype methods
  • preserve nested calls order
  • preserve context in cb()
  • preserve cb(args)
  • supports process.nextTick(cb)
  • supports setTimeout(cb)
  • supports methods redifinition
  • supports adding new methods
  • fully tested! local: npm install -g mocha && mocha, saucelabs: npm test

tests

See tests.

npm test

examples

See examples.

mixing async/sync apis

There is no easy way to mix sync/async chainable apis because there is no way to differenciate sync/async calls.

obj
  .asyncMethod()
  .syncMethod()

We cannot know that syncMethod is synchronous and that we do not need to wait for a callback to be called to continue.

Either your api is fully asynchronous and every method takes a callback.

Either your api is fully synchronous. If you want synchronous support, make a pull request adding chainit.sync(Constructor).

credits

This module is using jessetane/queue.

A chainable api is queueing methods and reordering calls, so we use a queue.

This module was built to replace the chainable api from webdriverjs.