Skip to content

Commit 3596eb1

Browse files
committed
[api] Add removeListenersByContext(context) method
1 parent 991b945 commit 3596eb1

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ differences:
1818
- The `setMaxListeners`, `getMaxListeners`, `prependListener` and
1919
`prependOnceListener` methods are not available.
2020
- Support for custom context for events so there is no need to use `fn.bind`.
21+
- There is an additional method named `removeListenersByContext`, which removes all listeners of the given
22+
context.
2123
- The `removeListener` method removes all matching listeners, not only the
2224
first.
2325

@@ -61,6 +63,9 @@ or `this` value that should be set for the emitted events. This means you no
6163
longer have the overhead of an event that required `fn.bind` in order to get a
6264
custom `this` value.
6365

66+
In addition to that, we have added a new method: `EventEmitter.removeListenersByContext`,
67+
which will remove all listeners of the given context.
68+
6469
```js
6570
var EE = new EventEmitter()
6671
, context = { foo: 'bar' };
@@ -72,6 +77,7 @@ function emitted() {
7277
EE.once('event-name', emitted, context);
7378
EE.on('another-event', emitted, context);
7479
EE.removeListener('another-event', emitted, context);
80+
EE.removeListenersByContext(context);
7581
```
7682

7783
### Tests and benchmarks

index.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ declare class EventEmitter<EventTypes extends string | symbol = string | symbol>
4747
* Remove all listeners, or those of the specified event.
4848
*/
4949
removeAllListeners(event?: EventTypes): this;
50+
51+
/**
52+
* Removes all listeners that were added with the specified context.
53+
*/
54+
removeListenersByContext(context?: any): this;
5055
}
5156

5257
declare namespace EventEmitter {

index.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,38 @@ EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
312312
return this;
313313
};
314314

315+
/**
316+
* Remove all listeners on a specific context.
317+
*
318+
* @param {*} context Only remove the listeners that have this context.
319+
* @returns {EventEmitter} `this`.
320+
* @public
321+
*/
322+
EventEmitter.prototype.removeListenersByContext = function removeListenersByContext(context) {
323+
var eventNames = this.eventNames();
324+
var totalListenerCount = 0;
325+
326+
for (var i = 0, eventsCount = eventNames.length; i < eventsCount; i++) {
327+
var evt = eventNames[i];
328+
var listeners = this._events[evt];
329+
330+
if (listeners.fn) listeners = [listeners];
331+
for (var j = 0, events = [], listenersCount = listeners.length; j < listenersCount; j++) {
332+
if (listeners[j].context !== context) events.push(listeners[j]);
333+
}
334+
335+
if (events.length) {
336+
this._events[evt] = events.length === 1 ? events[0] : events;
337+
totalListenerCount += events.length;
338+
} else {
339+
clearEvent(this, evt);
340+
}
341+
}
342+
343+
this._eventsCount = totalListenerCount;
344+
return this;
345+
};
346+
315347
//
316348
// Alias methods names because people roll like that.
317349
//

test/test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,35 @@ describe('EventEmitter', function tests() {
568568
});
569569
});
570570

571+
describe('EventEmitter#removeListenersByContext', function () {
572+
it('removes all listeners for the specified context', function () {
573+
var e = new EventEmitter();
574+
var ctx1 = {};
575+
var ctx2 = {};
576+
var ctx3 = {};
577+
578+
e.on('aaa', function () { throw new Error('oops'); }, ctx1);
579+
e.on('bbb', function () { throw new Error('oops'); }, ctx1);
580+
e.on('aaa', function () { throw new Error('oops'); }, ctx2);
581+
e.on('bbb', function () { throw new Error('oops'); }, ctx3);
582+
583+
assume(e.removeListenersByContext(ctx1)).equals(e);
584+
assume(e.listeners('aaa').length).equals(1);
585+
assume(e.listeners('bbb').length).equals(1);
586+
assume(e._eventsCount).equals(2);
587+
588+
assume(e.removeListenersByContext(ctx2)).equals(e);
589+
assume(e.listeners('aaa').length).equals(0);
590+
assume(e.listeners('bbb').length).equals(1);
591+
assume(e._eventsCount).equals(1);
592+
593+
assume(e.removeListenersByContext(ctx3)).equals(e);
594+
assume(e.listeners('aaa').length).equals(0);
595+
assume(e.listeners('bbb').length).equals(0);
596+
assume(e._eventsCount).equals(0);
597+
});
598+
});
599+
571600
describe('EventEmitter#eventNames', function () {
572601
it('returns an empty array when there are no events', function () {
573602
var e = new EventEmitter();

0 commit comments

Comments
 (0)