Skip to content

Commit

Permalink
Add: make use cases that do not include a core function or incoming d…
Browse files Browse the repository at this point in the history
…ata possible
  • Loading branch information
tmpvar committed Nov 17, 2011
1 parent 69817ee commit 0687042
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 4 deletions.
148 changes: 148 additions & 0 deletions README.md
@@ -0,0 +1,148 @@
# filterchain

Perform work before and/or after an operation.

## API Signature

```javascript
// Create a chain with no layers and no core function
var chain = require('filterchain').createChain(/* layers */, /* core */);
```

Where `chain` is a function that accepts an optional `data` and a required `callback` with the arguments `errors` and `data`. The `callback` is called after the filter chain has been executed.

`data` can be any javascript value

```javascript
// Except to show what the chain callback looks like
chain('some optional data', function(errors, data) {})
```

And `layers` is an array of functions

```javascript
var chain = require('filterchain').createChain([
function(data, next, cancel) {

// just forward the data, this is basically a no-op
next(data);
}
], core);
```

And `core` is the function that will be run after the capture phase but before the bubble phase. The `core` method should accept `data` and `fn`.

```javascript
var chain = require('filterchain').createChain([], function(data, fn) {

// send the incoming back the same way it came
if (data === true) {
fn(null, 'tricked ya!')
} else {
fn('error!')
}

});

chain(true, function(errors, data) {
console.log(data); // outputs: 'tricked ya!'
});

chain(false, function(errors, data) {
console.log(errors[0]); // outputs: 'error!'
console.log(data); // outputs: undefined
});

```

## What does it do?

In a sense, filter chains are similar to onions. Passing data into the outer husk causes it to flow down through each layer toward the core. Each function (aka: layer) along the path as a chance to either manipulate or validate the data before forwarding it onto the next layer or canceling it.

```javascript
var chain = require('filterchain').createChain([
function(data, next, cancel) {

// ignore the incoming data and forward something more
// to our liking
next('pass this along');
}
]);

chain(function(errors, data) {
console.log(data); // outputs 'pass this along'
});
```

Cancelling causes the flow of the chain to be reversed immediately.

```javascript
var chain = require('filterchain').createChain([
function(data, next, cancel) {

// the first argument to cancel is an optional error. The error
// will be collected and sent to the final callback for processing
cancel('fat chance');
}
], function(data, fn) {

// this is never called
fn('some other thing');
});

chain(function(errors, data) {
console.log(errors[0]); // ouputs 'fat chance'
});

```

The core of the filter chain is an optional function.

```javascript
var fc = require('filterchain');
var chain = fc.createChain([

])

```

## Basic Usage

The basic operation of filterchain goes something like this:

```javascript
var fc = require('filterchain');
var chain = fc.createChain([
function(data, next, cancel) {
next('override');
} // you can add more functions here
]);

chain('initial data', function(data) {
console.log(data); // outputs 'override'
});

```

## More interesting examples


```javascript
var fc = require('filterchain');
var chain = fc.createChain();

```



## Install

### Node.js

npm install filterchain

### Browser

works with just a script tag or an asynchronous module loading system like [require.js](http://requirejs.org/)


20 changes: 16 additions & 4 deletions index.js
@@ -1,9 +1,19 @@
(function() {
module.exports = {
createChain : function(chain, coreFn) {
chain = chain || [];
if (typeof chain === 'function' && !coreFn) {
coreFn = chain;
chain = [];
} else {
chain = chain || [];
}

var chainInstance = function(data, fn) {
if (typeof data === 'function' && !fn) {
fn = data;
data = null;
}

var
index = -1,
errors = [],
Expand Down Expand Up @@ -46,14 +56,16 @@
bubble(data);
});
} else {
//errors.push(new Error('user error! A link in the chain was not a function'))
//bubble(data);
errors.push(new Error('user error! A link in the chain was not a function'))
bubble(data);
}

}, bubble = function(data) {

if (bubbles.length < 1) {
fn((errors.length) ? errors : null, data);
if (fn) {
fn((errors.length) ? errors : null, data);
}
} else {
var bubbleFn = bubbles.pop();
var ret = bubbleFn(data, function done(err, data) {
Expand Down
17 changes: 17 additions & 0 deletions test.js
Expand Up @@ -26,6 +26,23 @@ basic({ hello : 'world' }, function(errors, data) {
equal('pre-world-post', data.hello);
});

// No provided data
var noData = fc.createChain([], function(data, fn) {
fn(null, 'this is some data')
});

noData(function(errors, data) {
equal('this is some data', data);
});

// No chain provided
var noChain = fc.createChain(function(data, fn) {
fn(null, data + ' world');
});

noChain('hello', function(errors, data) {
equal('hello world', data);
});

// Return from bubbler function
var bubbleReturn = fc.createChain([
Expand Down

0 comments on commit 0687042

Please sign in to comment.