From 1e9bd728a5b431b67cbf6b1bf595a1391eeeaea5 Mon Sep 17 00:00:00 2001 From: Matt Karl Date: Wed, 10 Aug 2016 15:08:26 -0400 Subject: [PATCH 1/3] Adds skip option --- index.js | 5 +++++ test.js | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/index.js b/index.js index 356d9bb..0a2d88b 100644 --- a/index.js +++ b/index.js @@ -42,6 +42,7 @@ function EE(fn, context, once) { this.fn = fn; this.context = context; this.once = once || false; + this.skip = false; } /** @@ -144,6 +145,7 @@ EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { for (i = 0; i < length; i++) { if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); + if (listeners[i].skip) continue; switch (len) { case 1: listeners[i].fn.call(listeners[i].context); break; @@ -236,6 +238,9 @@ EventEmitter.prototype.removeListener = function removeListener(event, fn, conte } } else { for (var i = 0, events = [], length = listeners.length; i < length; i++) { + if (!once && listeners[i].fn === fn) { + listeners[i].skip = true; + } if ( listeners[i].fn !== fn || (once && !listeners[i].once) diff --git a/test.js b/test.js index 879533d..b35ec8f 100644 --- a/test.js +++ b/test.js @@ -504,6 +504,29 @@ describe('EventEmitter', function tests() { assume(e.listeners('foo')).eql([]); assume(e._eventsCount).equals(0); }); + + it('removes a listener when removed as part handler callback', function() { + var e = new EventEmitter() + , foo = { bar: true } + , calledThird = 0; + + function first() { + foo = null; + e.removeListener('update', second); + } + function second() { + assume(foo.bar).equals(true); + } + function third() { + calledThird++; + } + e.on('update', first); + e.on('update', second); + e.on('update', third); + e.once('update', third); + e.emit('update'); + assume(calledThird).equals(2); + }); }); describe('EventEmitter#removeAllListeners', function () { From 59ea2723a0d1a3377ca1b7c6956ca52ede721315 Mon Sep 17 00:00:00 2001 From: Matt Karl Date: Wed, 10 Aug 2016 15:40:13 -0400 Subject: [PATCH 2/3] Adds an additional once, just in-case --- test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test.js b/test.js index b35ec8f..489ad44 100644 --- a/test.js +++ b/test.js @@ -522,6 +522,7 @@ describe('EventEmitter', function tests() { } e.on('update', first); e.on('update', second); + e.once('update', second); e.on('update', third); e.once('update', third); e.emit('update'); From eff8e915ec2db001bfcebe9fab9d06b4ac5a24e6 Mon Sep 17 00:00:00 2001 From: Matt Karl Date: Mon, 15 Aug 2016 12:19:55 -0400 Subject: [PATCH 3/3] Adds additional README description --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 92c3bea..a8b8280 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ differences: arrays. - The `removeListener` method removes all matching listeners, not only the first. +- When `removeListener` is called from within a handler for the same event + on a different object, it immediately removes the listener. It's a drop in replacement for existing EventEmitters, but just faster. Free performance, who wouldn't want that? The EventEmitter is written in EcmaScript 3