eventemitter-ex
Advanced tools
Comparing version 0.0.4 to 0.0.5
@@ -5,3 +5,4 @@ (function () { | ||
var EE = require('events').EventEmitter, | ||
util = require('util'); | ||
util = require('util'), | ||
assert = require('assert'); | ||
@@ -39,2 +40,13 @@ module.exports = EventEmitterEx; | ||
EventEmitterEx.prototype.emitAsync = function emitAsync (/* arguments */) { | ||
var args = arguments, | ||
self = this; | ||
setImmediate(function () { | ||
self.emit.apply(self, args); | ||
}); | ||
return this; | ||
}; | ||
EventEmitterEx.prototype.pipeExcept = function pipeExcept (ee) { | ||
@@ -91,4 +103,3 @@ var self = this, | ||
// flatten the array | ||
result = [].concat.apply([], result); | ||
result.unshift('end'); | ||
result = [].concat.apply(['end'], result); | ||
} catch (err) { | ||
@@ -104,2 +115,43 @@ eex.emit('error', err); | ||
// Takes zero or more functions and runs them in the same way as #map() but | ||
// also providing a callback as an additional last parameter. After all functions | ||
// had called the callback, results are emitted. | ||
EventEmitterEx.prototype.mapAsync = function mapAsync (/* arguments */) { | ||
var eex = new EventEmitterEx(), | ||
funcs = Array.prototype.slice.call(arguments); | ||
funcs.forEach(assertIsFunction); | ||
eex.pipeExcept(this, 'end'); | ||
this.on('end', function (/* arguments */) { | ||
var result = [], firstError, len = funcs.length; | ||
var endArgs = Array.prototype.slice.call(arguments); | ||
endArgs.push(callback); | ||
funcs.forEach(function (f) { | ||
f.apply(eex, endArgs); | ||
}); | ||
function callback (err/* arguments */) { | ||
if (err) { | ||
firstError = firstError || err; | ||
} else { | ||
result.push(Array.prototype.slice.call(arguments, 1)); | ||
} | ||
len--; | ||
assert(len >= 0, 'Callback called more than once for each mapAsync() function!'); | ||
if (! len) { | ||
if (firstError) { | ||
eex.emit('error', firstError); | ||
} else { | ||
// flatten the array | ||
eex.emit.apply(eex, [].concat.apply(['end'], result)); | ||
} | ||
} | ||
} | ||
}); | ||
return eex; | ||
}; | ||
EventEmitterEx.prototype.flatMap = function flatMap (f) { | ||
@@ -106,0 +158,0 @@ assertIsFunction(f); |
{ | ||
"name": "eventemitter-ex", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "EventEmitter extensions", | ||
@@ -5,0 +5,0 @@ "main": "EventEmitterEx.js", |
@@ -33,2 +33,30 @@ (function () { | ||
describe('#emitAsync()', function () { | ||
it('should call emit() asynchronously', function (done) { | ||
var spyEnd = sinon.spy(); | ||
emitter | ||
.on('error', done) | ||
.on('end1', spyEnd) | ||
.on('end', function () { | ||
spyEnd.calledWithExactly(1, 2, 3).should.be.true; | ||
done(); | ||
}) | ||
.emitAsync('end1', 1, 2, 3) | ||
.emitAsync('end') | ||
.should.be.equal(emitter); | ||
spyEnd.callCount.should.be.equal(0); | ||
}); | ||
it('should return self', function (done) { | ||
emitter | ||
.on('error', done) | ||
.on('end', done) | ||
.emitAsync('end').should.be.equal(emitter); | ||
}); | ||
}); | ||
describe('#pipeExcept()', function () { | ||
@@ -292,2 +320,103 @@ | ||
describe('#mapAsync()', function () { | ||
it('should throw if callback called too many times', function (done) { | ||
var mapped = emitter.mapAsync(function (cb) { | ||
cb(null); | ||
expect(function () { | ||
cb(null); | ||
}).to.throw(Error, 'Callback called more than once for each mapAsync() function!'); | ||
done(); | ||
}); | ||
mapped.on('error', done); | ||
emitter.emit('end'); | ||
}); | ||
it('should support synchronous call of callback', function (done) { | ||
var A = 42; | ||
var mapped = emitter.mapAsync(function (param, cb) { cb(null, param); }); | ||
mapped | ||
.on('end', function (result) { | ||
result.should.be.equal(A); | ||
done(); | ||
}) | ||
.on('error', done); | ||
emitter.emit('end', A); | ||
}); | ||
it('should support asynchronous call of callback', function (done) { | ||
var A = 42; | ||
var mapped = emitter.mapAsync(function (param, cb) { setImmediate(cb.bind(null, null, param)); }); | ||
mapped | ||
.on('end', function (result) { | ||
result.should.be.equal(A); | ||
done(); | ||
}) | ||
.on('error', done); | ||
emitter.emit('end', A); | ||
}); | ||
it('should set this to emitter', function (done) { | ||
var mapped = emitter.mapAsync(function (cb) { cb(null, this); }); | ||
mapped | ||
.on('end', function (result) { | ||
result.should.be.equal(mapped); | ||
done(); | ||
}) | ||
.on('error', done); | ||
emitter.emit('end'); | ||
}); | ||
it('should support returning multiple values as multiple arguments', function (done) { | ||
var A = 1, B = 2; | ||
var mapped = emitter.mapAsync(function (cb) { cb(null, A, B); }); | ||
mapped | ||
.on('end', function (a, b) { | ||
a.should.be.equal(A); | ||
b.should.be.equal(B); | ||
done(); | ||
}) | ||
.on('error', done); | ||
emitter.emit('end'); | ||
}); | ||
it('should emit exceptions as error', function (done) { | ||
var err = new Error('234'); | ||
emitter | ||
.mapAsync(function (cb) { cb(err); }) | ||
.on('end', function () { | ||
done(new Error('Expecting error')); | ||
}) | ||
.on('error', function (error) { | ||
error.should.be.equal(err); | ||
done(); | ||
}); | ||
emitter.emit('end'); | ||
}); | ||
it('should throw exception on non-function arguments', function () { | ||
expect(function () { | ||
emitter.mapAsync(function () {}, 2); | ||
}).to.throw(TypeError, /Argument must be a function/); | ||
}); | ||
it('should call each map function and return results in order', function (done) { | ||
var f1 = function (a1, a2, cb) { | ||
cb(null, a1 + a2); | ||
}; | ||
var f2 = function (a1, a2, cb) { | ||
cb(null, a1 * a2); | ||
}; | ||
var r = emitter.mapAsync(f1, f2); | ||
r.on('end', function (r1, r2) { | ||
r1.should.be.equal(6); | ||
r2.should.be.equal(8); | ||
done(); | ||
}); | ||
emitter.emit('end', 4, 2); | ||
}); | ||
}); | ||
describe('#flatMap()', function () { | ||
@@ -294,0 +423,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
40860
609