finally
Advanced tools
Comparing version 0.1.1 to 0.2.0
60
index.js
@@ -11,3 +11,9 @@ /* | ||
var forEach = require('mout/array/forEach'); | ||
var reduce = require('mout/array/reduce'); | ||
var each = require('mout/collection/forEach'); | ||
var cmap = require('mout/collection/map'); | ||
var push_ = Array.prototype.push; | ||
/* create the flow */ | ||
@@ -22,27 +28,48 @@ var Flow = prime({ | ||
/* add steps to the flow */ | ||
then: function(callbacks) { | ||
then: function() { | ||
this._push(this._callbacks(arguments)); | ||
return this; | ||
}, | ||
_parallel: function(parallel, args) { | ||
var self = this; | ||
if (!arguments.length) return this; | ||
if (kindOf(callbacks) !== 'Array') callbacks = slice(arguments); | ||
if (!callbacks.length) return this; | ||
var i = 0; | ||
var exec = function(fn, index, args) { | ||
var control = new Controller(self, index); | ||
return function() { | ||
var control = new Controller(self, self._index++); | ||
self._controls.push(control); | ||
fn.apply(control, args); | ||
parallel.apply(control, args ? args.concat(slice(arguments)) : arguments); | ||
}; | ||
}, | ||
this._seq.push(map(callbacks, function(parallel) { | ||
_push: function(parallels, args) { | ||
if (!parallels.length) return; | ||
this._seq.push(map(parallels, function(parallel) { | ||
return this._parallel(parallel, args); | ||
}, this)); | ||
}, | ||
return function() { | ||
var j = i++; | ||
exec(parallel, j, arguments); | ||
}; | ||
_callbacks: function(callbacks) { | ||
return reduce(callbacks, function(a, b) { | ||
if (kindOf(b) === 'Array') push_.apply(a, b); | ||
else a.push(b); | ||
return a; | ||
}, []); | ||
}, | ||
})); | ||
/* will make a sequential entry for each entry in the object */ | ||
sequential: function(object) { | ||
var callbacks = this._callbacks(slice(arguments, 1)); | ||
each(object, function(value, key) { | ||
this._push(callbacks, [value, key]); | ||
}, this); | ||
return this; | ||
}, | ||
/* will make a single sequential entry with one parallel for each entry in the object */ | ||
parallel: function(object, parallel) { | ||
this._seq.push(cmap(object, function(value, key) { | ||
return this._parallel(parallel, [value, key]); | ||
}, this)); | ||
return this; | ||
}, | ||
/* assign last step and execute the flow */ | ||
@@ -101,2 +128,3 @@ finally: function() { | ||
this._controls = []; | ||
this._index = 0; | ||
@@ -103,0 +131,0 @@ return seq; |
{ | ||
"name": "finally", | ||
"version": "0.1.1", | ||
"version": "0.2.0", | ||
"description": "sane flow control library", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
148
README.md
@@ -17,15 +17,15 @@ Finally | ||
flow(function(){ | ||
fs.readFile('path/to/file', 'utf-8', this.continue) | ||
// this.continue is a node-style callback that also triggers the next sequential | ||
fs.readFile('path/to/file', 'utf-8', this.continue) | ||
// this.continue is a node-style callback that also triggers the next sequential | ||
}) | ||
.then(function(error, data1){ | ||
if (error) this.break(error) | ||
// this.break is a node-style callback that also triggers the last sequential | ||
fs.readFile('path/to/file', 'utf-8', function(error, data2) { | ||
this.continue(error, data1, data2) | ||
}.bind(this)) | ||
if (error) this.break(error) | ||
// this.break is a node-style callback that also triggers the last sequential | ||
fs.readFile('path/to/file', 'utf-8', function(error, data2) { | ||
this.continue(error, data1, data2) | ||
}.bind(this)) | ||
}) | ||
.finally(function(error, data1, data2){ | ||
if (error) throw error | ||
console.log(data1, data2) | ||
if (error) throw error | ||
console.log(data1, data2) | ||
}) | ||
@@ -41,15 +41,15 @@ ``` | ||
flow( | ||
function(){ | ||
fs.readFile('path/to/file', 'utf-8', this.done) | ||
// this.done is a node-style callback that increments the parallels counter and | ||
// triggers the next sequential when all are completed. | ||
// the first argument passed to done is then distributed, in order, to the next sequential | ||
}, | ||
function(){ | ||
fs.readFile('path/to/file', 'utf-8', this.done) | ||
}, | ||
function(){ | ||
fs.readFile('path/to/file', 'utf-8', this.done) | ||
// this.done is a node-style callback that increments the parallels counter and | ||
// triggers the next sequential when all are completed. | ||
// the first argument passed to done is then distributed, in order, to the next sequential | ||
}, | ||
function(){ | ||
fs.readFile('path/to/file', 'utf-8', this.done) | ||
}, | ||
) | ||
.finally(function(error, data1, data2){ | ||
if (error) throw error | ||
else console.log(data1, data2) | ||
if (error) throw error | ||
else console.log(data1, data2) | ||
}) | ||
@@ -77,7 +77,7 @@ ``` | ||
.then(function(error, n){ | ||
this.done(error, n + 1) | ||
this.done(error, n + 1) | ||
}) | ||
.finally(function(error, n1, n2, n3, n4, n5){ | ||
if (error) throw error | ||
else console.log(n1, n2, n3, n4, n5) // [1,2,3,4,5] | ||
if (error) throw error | ||
else console.log(n1, n2, n3, n4, n5) // [1,2,3,4,5] | ||
}) | ||
@@ -101,20 +101,20 @@ ``` | ||
.then(function(error, n){ | ||
fs.readFile('path/to/file2', function(error, data){ | ||
if (error) this.continue(error) | ||
else this.break(null, 'path/to/file2', data) | ||
}.bind(this)) | ||
fs.readFile('path/to/file2', function(error, data){ | ||
if (error) this.continue(error) | ||
else this.break(null, 'path/to/file2', data) | ||
}.bind(this)) | ||
}) | ||
.then(function(error, n){ | ||
fs.readFile('path/to/file3', function(error, data){ | ||
if (error) this.continue(error) | ||
else this.break(null, 'path/to/file3', data) | ||
}.bind(this)) | ||
fs.readFile('path/to/file3', function(error, data){ | ||
if (error) this.continue(error) | ||
else this.break(null, 'path/to/file3', data) | ||
}.bind(this)) | ||
}) | ||
.finally(function(error, path, data){ | ||
if (error) console.log('no existing file found') | ||
else console.log('first existing file was ' + path + ' with data ' + data) | ||
if (error) console.log('no existing file found') | ||
else console.log('first existing file was ' + path + ' with data ' + data) | ||
}) | ||
``` | ||
But we can also automatically generate it: | ||
## Reading files sequentially, generating the flow | ||
@@ -128,15 +128,79 @@ ```js | ||
['path/to/file1', 'path/to/file2', 'path/to/file3'].forEach(function(path) { | ||
ƒ.then(function(error){ | ||
fs.readFile(path, function(error, data){ | ||
if (error) this.continue(error) | ||
else this.break(null, path, data) | ||
}.bind(this)) | ||
}) | ||
ƒ.then(function(error){ | ||
fs.readFile(path, function(error, data){ | ||
if (error) this.continue(error) | ||
else this.break(null, path, data) | ||
}.bind(this)) | ||
}) | ||
}) | ||
ƒ.finally(function(error, path, data){ | ||
if (error) console.log('no existing file found') | ||
else console.log('first existing file was ' + path + ' with data ' + data) | ||
if (error) console.log('no existing file found') | ||
else console.log('first existing file was ' + path + ' with data ' + data) | ||
}) | ||
``` | ||
There is also a shortcut for the above: | ||
```js | ||
var fs = require('fs') | ||
var flow = require('finally') | ||
var ƒ = flow() | ||
ƒ.sequential(['path/to/file1', 'path/to/file2', 'path/to/file3'], function(path, i, error) { | ||
fs.readFile(path, function(error, data){ | ||
if (error) this.continue(error) | ||
else this.break(null, path, data) | ||
}.bind(this)) | ||
}) | ||
ƒ.finally(function(error, path, data){ | ||
if (error) console.log('no existing file found') | ||
else console.log('first existing file was ' + path + ' with data ' + data) | ||
}) | ||
``` | ||
## Reading files in parallel, generating the flow | ||
```js | ||
var fs = require('fs') | ||
var flow = require('finally') | ||
var ƒ = flow() | ||
ƒ(['path/to/file1', 'path/to/file2', 'path/to/file3'].map(function(path) { | ||
return function(error){ | ||
fs.readFile(path, function(error, data){ | ||
if (error) this.done(error) | ||
else this.break(null, path, data) | ||
}.bind(this)) | ||
} | ||
}) | ||
ƒ.finally(function(error, path, data){ | ||
if (error) console.log('no existing file found') | ||
else console.log('first existing file was ' + path + ' with data ' + data) | ||
}) | ||
``` | ||
There is also a shortcut for the above: | ||
```js | ||
var fs = require('fs') | ||
var flow = require('finally') | ||
var ƒ = flow() | ||
ƒ.parallel(['path/to/file1', 'path/to/file2', 'path/to/file3'], function(path, i, error) { | ||
fs.readFile(path, function(error, data){ | ||
if (error) this.done(error) | ||
else this.break(null, path, data) | ||
}.bind(this)) | ||
}) | ||
ƒ.finally(function(error, path, data){ | ||
if (error) console.log('no existing file found') | ||
else console.log('first existing file was ' + path + ' with data ' + data) | ||
}) | ||
``` |
@@ -10,3 +10,3 @@ "use strict" | ||
it('should accept a last step in finally', function() { | ||
it('should accept a last step', function() { | ||
@@ -29,3 +29,3 @@ flow() | ||
it('should accept a first step in the constructor and a last step in finally', function() { | ||
it('should accept a first step in the constructor and a last step', function() { | ||
@@ -187,2 +187,50 @@ flow(function() { | ||
it('should map an array to a sequential', function() { | ||
flow() | ||
.sequential([1,4,5], function(item, i, err, num) { | ||
this.continue(null, item + num) | ||
}) | ||
.then(function(error, res) { | ||
expect(res).to.be(10) | ||
}) | ||
.run(null, 0) | ||
}) | ||
it('should map an object to a sequential', function() { | ||
flow() | ||
.sequential({a: 1, b: 4, c: 5}, function(value, key, err, num) { | ||
this.continue(null, value + num) | ||
}) | ||
.then(function(error, res) { | ||
expect(res).to.be(10) | ||
}) | ||
.run(null, 0) | ||
}) | ||
it('should map an array to parallels', function() { | ||
flow() | ||
.parallel([1,2,4], function(item, i, err, num) { | ||
this.done(null, item + num) | ||
}) | ||
.then(function(error) { | ||
var num = 0 | ||
for (var i = 1; i < arguments.length; i++) num += arguments[i] | ||
expect(num).to.be(10) | ||
}) | ||
.run(null, 1) | ||
}) | ||
it('should map an object to parallels', function() { | ||
flow() | ||
.parallel({a: 1, b: 2, c: 4}, function(value, key, err, num) { | ||
this.done(null, value + num) | ||
}) | ||
.then(function(error) { | ||
var num = 0 | ||
for (var i = 1; i < arguments.length; i++) num += arguments[i] | ||
expect(num).to.be(10) | ||
}) | ||
.run(null, 1) | ||
}) | ||
}) | ||
@@ -192,3 +240,3 @@ | ||
it('should accept a last step in finally', function(done) { | ||
it('should accept a last step', function(done) { | ||
@@ -218,3 +266,3 @@ flow() | ||
it('should accept a first step in the constructor and a last step in finally', function(done) { | ||
it('should accept a first step in the constructor and a last step', function(done) { | ||
@@ -343,4 +391,63 @@ flow(function() { | ||
it('should map an array to a sequential', function() { | ||
flow() | ||
.sequential([1,4,5], function(item, i, err, num) { | ||
setTimeout((function() { | ||
this.continue(null, item + num) | ||
}).bind(this), 10) | ||
}) | ||
.then(function(error, res) { | ||
expect(res).to.be(10) | ||
}) | ||
.run(null, 0) | ||
}) | ||
it('should map an object to a sequential', function(done) { | ||
flow() | ||
.sequential({a: 1, b: 4, c: 5}, function(value, key, err, num) { | ||
setTimeout((function() { | ||
this.continue(null, value + num) | ||
}).bind(this), 10) | ||
}) | ||
.then(function(error, res) { | ||
expect(res).to.be(10) | ||
done() | ||
}) | ||
.run(null, 0) | ||
}) | ||
it('should map an array to parallels', function(done) { | ||
flow() | ||
.parallel([1,2,4], function(item, i, err, num) { | ||
setTimeout((function() { | ||
this.done(null, item + num) | ||
}).bind(this), 10 - item) | ||
}) | ||
.then(function(error) { | ||
var num = 0 | ||
for (var i = 1; i < arguments.length; i++) num += arguments[i] | ||
expect(num).to.be(10) | ||
done() | ||
}) | ||
.run(null, 1) | ||
}) | ||
it('should map an object to parallels', function(done) { | ||
flow() | ||
.parallel({a: 1, b: 2, c: 4}, function(value, key, err, num) { | ||
setTimeout((function() { | ||
this.done(null, value + num) | ||
}).bind(this), 10 - value) | ||
}) | ||
.then(function(error) { | ||
var num = 0 | ||
for (var i = 1; i < arguments.length; i++) num += arguments[i] | ||
expect(num).to.be(10) | ||
done() | ||
}) | ||
.run(null, 1) | ||
}) | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
529
202
21985
6