Comparing version 0.3.3 to 0.3.5
131
index.js
@@ -299,3 +299,3 @@ var EventEmitter = require('events').EventEmitter; | ||
var res = []; | ||
var len = context.stack.length; | ||
var lastIdx = context.stack.length - 1; | ||
@@ -307,3 +307,4 @@ this.seqEach(function (x, i) { | ||
res[i] = arguments[1]; | ||
if (i == len - 1) context.stack = res; | ||
if (i === lastIdx) | ||
context.stack = res; | ||
self.apply(self, arguments); | ||
@@ -321,2 +322,4 @@ }; | ||
res[key] = arguments[1]; | ||
if (i === lastIdx) | ||
context.stack = res; | ||
self.apply(self, arguments); | ||
@@ -336,3 +339,108 @@ }; | ||
[ 'forEach', 'seqEach', 'parEach', 'seqMap', 'parMap' ] | ||
/** | ||
* Consumes any errors that occur in `cb`. Calls to `this.into(i)` will place | ||
* that value, if accepted by the filter, at the index in the results as | ||
* if it were the i-th index before filtering. (This means it will never | ||
* override another value, and will only actually appear at i if the filter | ||
* accepts all values before i.) | ||
*/ | ||
this.parFilter = function (limit, cb) { | ||
var res = []; | ||
var len = context.stack.length; | ||
if (cb === undefined) { cb = limit; limit = len } | ||
var res = []; | ||
Seq() | ||
.extend(context.stack) | ||
.parEach(limit, function (x, i) { | ||
var self = this; | ||
var next = function (err, ok) { | ||
if (!err && ok) | ||
res.push([i, x]); | ||
arguments[0] = null; // discard errors | ||
self.apply(self, arguments); | ||
}; | ||
next.stack = self.stack; | ||
next.stack_ = self.stack_; | ||
next.vars = self.vars; | ||
next.args = self.args; | ||
next.error = self.error; | ||
next.into = function (key) { | ||
return function (err, ok) { | ||
if (!err && ok) | ||
res.push([key, x]); | ||
arguments[0] = null; // discard errors | ||
self.apply(self, arguments); | ||
}; | ||
}; | ||
next.ok = function () { | ||
var args = [].slice.call(arguments); | ||
args.unshift(null); | ||
return next.apply(next, args); | ||
}; | ||
cb.apply(next, arguments); | ||
}) | ||
.seq(function () { | ||
context.stack = res.sort().map(function(pair){ return pair[1]; }); | ||
saw.next(); | ||
}) | ||
; | ||
}; | ||
/** | ||
* Consumes any errors that occur in `cb`. Calls to `this.into(i)` will place | ||
* that value, if accepted by the filter, at the index in the results as | ||
* if it were the i-th index before filtering. (This means it will never | ||
* override another value, and will only actually appear at i if the filter | ||
* accepts all values before i.) | ||
*/ | ||
this.seqFilter = function (cb) { | ||
var res = []; | ||
var lastIdx = context.stack.length - 1; | ||
this.seqEach(function (x, i) { | ||
var self = this; | ||
var next = function (err, ok) { | ||
if (!err && ok) | ||
res.push([i, x]); | ||
if (i === lastIdx) | ||
context.stack = res.sort().map(function(pair){ return pair[1]; }); | ||
arguments[0] = null; // discard errors | ||
self.apply(self, arguments); | ||
}; | ||
next.stack = self.stack; | ||
next.stack_ = self.stack_; | ||
next.vars = self.vars; | ||
next.args = self.args; | ||
next.error = self.error; | ||
next.into = function (key) { | ||
return function (err, ok) { | ||
if (!err && ok) | ||
res.push([key, x]); | ||
if (i === lastIdx) | ||
context.stack = res.sort().map(function(pair){ return pair[1]; }); | ||
arguments[0] = null; // discard errors | ||
self.apply(self, arguments); | ||
}; | ||
}; | ||
next.ok = function () { | ||
var args = [].slice.call(arguments); | ||
args.unshift(null); | ||
return next.apply(next, args); | ||
}; | ||
cb.apply(next, arguments); | ||
}); | ||
}; | ||
[ 'forEach', 'seqEach', 'parEach', 'seqMap', 'parMap', 'seqFilter', 'parFilter' ] | ||
.forEach(function (name) { | ||
@@ -349,3 +457,3 @@ this[name + '_'] = function (cb) { | ||
['push','pop','shift','unshift','splice'] | ||
['push','pop','shift','unshift','splice','reverse'] | ||
.forEach(function (name) { | ||
@@ -363,2 +471,17 @@ this[name] = function () { | ||
[ 'map', 'filter', 'reduce' ] | ||
.forEach(function (name) { | ||
this[name] = function () { | ||
var res = context.stack[name].apply( | ||
context.stack, | ||
[].slice.call(arguments) | ||
); | ||
// stack must be an array, or bad things happen | ||
context.stack = (Array.isArray(res) ? res : [res]); | ||
saw.next(); | ||
return this; | ||
}; | ||
}, this) | ||
; | ||
this.extend = function (xs) { | ||
@@ -365,0 +488,0 @@ if (!Array.isArray(xs)) { |
{ | ||
"name" : "seq", | ||
"version" : "0.3.3", | ||
"version" : "0.3.5", | ||
"description" : "Chainable asynchronous flow control with sequential and parallel primitives and pipeline-style error handling", | ||
@@ -15,3 +15,3 @@ "main" : "./index.js", | ||
"devDependencies" : { | ||
"expresso" : "=0.7.x" | ||
"expresso" : ">=0.7.x" | ||
}, | ||
@@ -18,0 +18,0 @@ "script" : { |
173
test/seq.js
@@ -172,6 +172,6 @@ var Seq = require('seq'); | ||
.par('one', function() { | ||
setTimeout(this.bind({}, 'rawr1'), 25); | ||
setTimeout(this.bind({}, 'rawr1'), 25); | ||
}) | ||
.par('two', function() { | ||
setTimeout(this.bind({}, 'rawr2'), 50); | ||
setTimeout(this.bind({}, 'rawr2'), 50); | ||
}) | ||
@@ -461,2 +461,20 @@ .catch(function(err,key) { | ||
exports.parMapInto = function () { | ||
var to = setTimeout(function () { | ||
assert.fail('never finished'); | ||
}, 500); | ||
var values = []; | ||
Seq([1,2,3,4,5,6,7,8,9,10]) | ||
.parMap(function (x, i) { | ||
this.into(9 - i)(null, x * 10); | ||
}) | ||
.seq(function () { | ||
clearTimeout(to); | ||
assert.eql(this.stack, [100, 90, 80, 70, 60, 50, 40, 30, 20, 10]); | ||
assert.eql(this.stack, [].slice.call(arguments)); | ||
}) | ||
; | ||
}; | ||
exports.seqMap = function () { | ||
@@ -487,2 +505,130 @@ var to = setTimeout(function () { | ||
exports.seqMapInto = function () { | ||
var to = setTimeout(function () { | ||
assert.fail('never finished'); | ||
}, 500); | ||
var running = 0; | ||
var values = []; | ||
Seq([1,2,3,4,5,6,7,8,9,10]) | ||
.seqMap(function (x, i) { | ||
running ++; | ||
assert.eql(running, 1); | ||
setTimeout((function () { | ||
running --; | ||
this.into(9 - i)(null, x * 10); | ||
}).bind(this), 10); | ||
}) | ||
.seq(function () { | ||
clearTimeout(to); | ||
assert.eql(this.stack, [100, 90, 80, 70, 60, 50, 40, 30, 20, 10]); | ||
}) | ||
; | ||
}; | ||
exports.parFilter = function () { | ||
var to = setTimeout(function () { | ||
assert.fail('never finished'); | ||
}, 500); | ||
var running = 0; | ||
var values = []; | ||
Seq([1,2,3,4,5,6,7,8,9,10]) | ||
.parFilter(2, function (x, i) { | ||
running ++; | ||
assert.ok(running <= 2); | ||
setTimeout((function () { | ||
running --; | ||
this(null, x % 2 === 0); | ||
}).bind(this), Math.floor(Math.random() * 100)); | ||
}) | ||
.seq(function () { | ||
clearTimeout(to); | ||
assert.eql(this.stack, [2,4,6,8,10]); | ||
assert.eql(this.stack, [].slice.call(arguments)); | ||
}) | ||
; | ||
}; | ||
exports.seqFilter = function () { | ||
var to = setTimeout(function () { | ||
assert.fail('never finished'); | ||
}, 500); | ||
var running = 0; | ||
var values = []; | ||
Seq([1,2,3,4,5,6,7,8,9,10]) | ||
.seqFilter(function (x, i) { | ||
running ++; | ||
assert.eql(running, 1); | ||
setTimeout((function () { | ||
running --; | ||
this(null, x % 2 === 0); | ||
}).bind(this), 10); | ||
}) | ||
.seq(function () { | ||
clearTimeout(to); | ||
assert.eql(this.stack, [2,4,6,8,10]); | ||
}) | ||
; | ||
}; | ||
exports.parFilterInto = function () { | ||
var to = setTimeout(function () { | ||
assert.fail('never finished'); | ||
}, 500); | ||
var running = 0; | ||
var values = []; | ||
Seq([1,2,3,4,5,6,7,8,9,10]) | ||
.parFilter(2, function (x, i) { | ||
running ++; | ||
assert.ok(running <= 2); | ||
setTimeout((function () { | ||
running --; | ||
this.into(x % 3)(null, x % 2 === 0); | ||
}).bind(this), Math.floor(Math.random() * 100)); | ||
}) | ||
.seq(function () { | ||
clearTimeout(to); | ||
assert.eql(this.stack, [ 6, 10, 4, 2, 8 ]); | ||
assert.eql(this.stack, [].slice.call(arguments)); | ||
}) | ||
; | ||
}; | ||
exports.seqFilterInto = function () { | ||
var to = setTimeout(function () { | ||
assert.fail('never finished'); | ||
}, 500); | ||
var running = 0; | ||
var values = []; | ||
Seq([1,2,3,4,5,6,7,8,9,10]) | ||
.seqFilter(function (x, i) { | ||
running ++; | ||
assert.eql(running, 1); | ||
setTimeout((function () { | ||
running --; | ||
this.into(x % 3)(null, x % 2 === 0); | ||
}).bind(this), 10); | ||
}) | ||
.seq(function () { | ||
clearTimeout(to); | ||
assert.eql(this.stack, [ 6, 10, 4, 2, 8 ]); | ||
}) | ||
; | ||
}; | ||
exports.stack = function () { | ||
@@ -557,4 +703,25 @@ var to = setTimeout(function () { | ||
assert.eql(this.stack, ['a','b','e']); | ||
this(null); | ||
this.pass(null); | ||
}) | ||
.reverse() | ||
.seq(function (a, b, e){ | ||
assert.eql(arguments.length, 3); | ||
assert.eql([a,b,e], ['e','b','a']); | ||
assert.eql(this.stack, ['e','b','a']); | ||
this.pass(null); | ||
}) | ||
.map(function(ch){ return ch.toUpperCase(); }) | ||
.seq(function (A, B, E){ | ||
assert.eql(arguments.length, 3); | ||
assert.eql([A,B,E], ['E','B','A']); | ||
assert.eql(this.stack, ['E','B','A']); | ||
this.pass(null); | ||
}) | ||
.reduce(function(s, ch){ return s + ':' + ch; }) | ||
.seq(function (acc){ | ||
assert.eql(arguments.length, 1); | ||
assert.eql(acc, 'E:B:A'); | ||
assert.eql(this.stack, ['E:B:A']); | ||
this.pass(null); | ||
}) | ||
.seq(function () { | ||
@@ -561,0 +728,0 @@ clearTimeout(to); |
Sorry, the diff of this file is not supported yet
60473
1515
443