UNPKG

peer-emitter

Version:

acknowledgeable events

150 lines (107 loc) 3.31 kB
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; }