peer-emitter
Version:
acknowledgeable events
150 lines (107 loc) • 3.31 kB
JavaScript
var DuplexEmiter = require('duplex-emitter');
var WriteStream = require('./write-stream');
var ReadStream = require('./read-stream');
module.exports = PeerEmitter;
function PeerEmitter(duplexStream, options) {
options = options || {};
var duplexEmitter = DuplexEmiter(duplexStream);
var listeners = {};
var emitter = {};
emitter.emit = emit;
function emit() {
var args = [].slice.call(arguments);
var evtName = args[0];
var meta = {};
var timeout;
var cb;
if (typeof args[args.length - 1] === 'function') {
var ackEvtName = '_ack_' + Math.random().toString().slice(2);
meta.ack = ackEvtName;
cb = args.pop();
duplexEmitter.once(ackEvtName, ackHandler);
}
function ackHandler() {
if (timeout)
clearTimeout(timeout);
cb();
}
args.splice(1, 0, meta);
var timeoutVal = cb && cb.timeout || options.timeout;
if (cb && timeoutVal) {
timeout = setTimeout(function() {
cb(true);
duplexEmitter.removeListener(ackEvtName, ackHandler);
}, timeoutVal);
}
duplexEmitter.emit.apply(duplexEmitter, args);
}
emitter.on = emitter.addListener = on;
function on(evtName, handler) {
var handlers = listeners[evtName] = listeners[evtName] || [];
if (handlers.some(function(h) { return h.handler === handler; }))
return;
duplexEmitter.on(evtName, internalHandler);
function internalHandler() {
var args = [].slice.call(arguments);
var meta = args.splice(0, 1)[0];
var realHandler = handler.realHandler || handler;
var auto = realHandler.length <= args.length;
if (meta.ack)
args.push(ack);
function ack() {
duplexEmitter.emit(meta.ack);
}
handler.apply(null, args);
if (meta.ack && auto)
ack();
}
handlers.push({
handler: handler,
internalHandler: internalHandler
});
}
emitter.removeListener = removeListener;
function removeListener(evtName, handler) {
var handlers = listeners[evtName] = listeners[evtName] || [];
for (var i = 0; i < handlers.length; ++i) {
var obj = handlers[i];
if (obj.handler !== handler)
continue;
duplexEmitter.removeListener(evtName, obj.internalHandler);
}
}
emitter.once = once;
function once(evtName, handler) {
function fire() {
removeListener(evtName, fire);
handler.apply(this, arguments);
}
fire.realHandler = handler;
on(evtName, fire);
}
emitter.removeAllListeners = removeAllListeners;
function removeAllListeners(evtName) {
if (evtName)
return removeAllEvtListeners(evtName);
Object.keys(listeners).forEach(removeAllEvtListeners);
}
function removeAllEvtListeners(evtName) {
var handlers = listeners[evtName];
if (! handlers)
return;
duplexEmitter.removeAllListeners(evtName);
delete handlers[evtName];
}
emitter.ReadStream = createReadStream;
function createReadStream(name) {
return ReadStream(emitter, name);
}
emitter.WriteStream = createWriteStream;
function createWriteStream(name) {
return WriteStream(emitter, name);
}
duplexStream.on('end', function() {
duplexEmitter.removeAllListeners();
});
return emitter;
}