mirror of https://github.com/nodejs/node.git
events: add 'removeListener' event
parent
d0e6c3f5a6
commit
84221fd1d6
|
@ -26,7 +26,7 @@ If there is no listener for it, then the default action is to print a stack
|
|||
trace and exit the program.
|
||||
|
||||
All EventEmitters emit the event `'newListener'` when new listeners are
|
||||
added.
|
||||
added and `'removeListener'` when a listener is removed.
|
||||
|
||||
### emitter.addListener(event, listener)
|
||||
### emitter.on(event, listener)
|
||||
|
|
|
@ -191,6 +191,7 @@ EventEmitter.prototype.once = function(type, listener) {
|
|||
return this;
|
||||
};
|
||||
|
||||
// emits a 'removeListener' event iff the listener was removed
|
||||
EventEmitter.prototype.removeListener = function(type, listener) {
|
||||
if ('function' !== typeof listener) {
|
||||
throw new Error('removeListener only takes instances of Function');
|
||||
|
@ -216,23 +217,41 @@ EventEmitter.prototype.removeListener = function(type, listener) {
|
|||
list.splice(position, 1);
|
||||
if (list.length == 0)
|
||||
delete this._events[type];
|
||||
this.emit('removeListener', type, listener);
|
||||
} else if (list === listener ||
|
||||
(list.listener && list.listener === listener))
|
||||
{
|
||||
delete this._events[type];
|
||||
this.emit('removeListener', type, listener);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
EventEmitter.prototype.removeAllListeners = function(type) {
|
||||
if (!this._events) return this;
|
||||
|
||||
if (arguments.length === 0) {
|
||||
for (var key in this._events) {
|
||||
if (key === 'removeListener') continue;
|
||||
this.removeAllListeners(key);
|
||||
}
|
||||
this.removeAllListeners('removeListener');
|
||||
this._events = {};
|
||||
return this;
|
||||
}
|
||||
|
||||
// does not use listeners(), so no side effect of creating _events[type]
|
||||
if (type && this._events && this._events[type]) this._events[type] = null;
|
||||
var listeners = this._events[type];
|
||||
if (isArray(listeners)) {
|
||||
while (listeners.length) {
|
||||
// LIFO order
|
||||
this.removeListener(type, listeners[listeners.length - 1]);
|
||||
}
|
||||
} else if (listeners) {
|
||||
this.removeListener(type, listeners);
|
||||
}
|
||||
this._events[type] = null;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
|
|
|
@ -24,6 +24,17 @@ var assert = require('assert');
|
|||
var events = require('events');
|
||||
|
||||
|
||||
function expect(expected) {
|
||||
var actual = [];
|
||||
process.on('exit', function() {
|
||||
assert.deepEqual(actual.sort(), expected.sort());
|
||||
});
|
||||
function listener(name) {
|
||||
actual.push(name)
|
||||
}
|
||||
return common.mustCall(listener, expected.length);
|
||||
}
|
||||
|
||||
function listener() {}
|
||||
|
||||
var e1 = new events.EventEmitter();
|
||||
|
@ -34,6 +45,7 @@ e1.on('baz', listener);
|
|||
var fooListeners = e1.listeners('foo');
|
||||
var barListeners = e1.listeners('bar');
|
||||
var bazListeners = e1.listeners('baz');
|
||||
e1.on('removeListener', expect(['bar', 'baz', 'baz']));
|
||||
e1.removeAllListeners('bar');
|
||||
e1.removeAllListeners('baz');
|
||||
assert.deepEqual(e1.listeners('foo'), [listener]);
|
||||
|
@ -52,6 +64,9 @@ assert.notEqual(e1.listeners('baz'), bazListeners);
|
|||
var e2 = new events.EventEmitter();
|
||||
e2.on('foo', listener);
|
||||
e2.on('bar', listener);
|
||||
// expect LIFO order
|
||||
e2.on('removeListener', expect(['foo', 'bar', 'removeListener']));
|
||||
e2.on('removeListener', expect(['foo', 'bar']));
|
||||
e2.removeAllListeners();
|
||||
console.error(e2);
|
||||
assert.deepEqual([], e2.listeners('foo'));
|
||||
|
|
|
@ -23,7 +23,6 @@ var common = require('../common');
|
|||
var assert = require('assert');
|
||||
var events = require('events');
|
||||
|
||||
|
||||
var count = 0;
|
||||
|
||||
function listener1() {
|
||||
|
@ -41,21 +40,45 @@ function listener3() {
|
|||
count++;
|
||||
}
|
||||
|
||||
function remove1() {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
function remove2() {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
var e1 = new events.EventEmitter();
|
||||
e1.on('hello', listener1);
|
||||
e1.on('removeListener', common.mustCall(function(name, cb) {
|
||||
assert.equal(name, 'hello');
|
||||
assert.equal(cb, listener1);
|
||||
}));
|
||||
e1.removeListener('hello', listener1);
|
||||
assert.deepEqual([], e1.listeners('hello'));
|
||||
|
||||
var e2 = new events.EventEmitter();
|
||||
e2.on('hello', listener1);
|
||||
e2.on('removeListener', assert.fail);
|
||||
e2.removeListener('hello', listener2);
|
||||
assert.deepEqual([listener1], e2.listeners('hello'));
|
||||
|
||||
var e3 = new events.EventEmitter();
|
||||
e3.on('hello', listener1);
|
||||
e3.on('hello', listener2);
|
||||
e3.on('removeListener', common.mustCall(function(name, cb) {
|
||||
assert.equal(name, 'hello');
|
||||
assert.equal(cb, listener1);
|
||||
}));
|
||||
e3.removeListener('hello', listener1);
|
||||
assert.deepEqual([listener2], e3.listeners('hello'));
|
||||
|
||||
|
||||
|
||||
var e4 = new events.EventEmitter();
|
||||
e4.on('removeListener', common.mustCall(function(name, cb) {
|
||||
if (cb !== remove1) return;
|
||||
this.removeListener('quux', remove2);
|
||||
this.emit('quux');
|
||||
}, 2));
|
||||
e4.on('quux', remove1);
|
||||
e4.on('quux', remove2);
|
||||
e4.removeListener('quux', remove1);
|
||||
|
|
Loading…
Reference in New Issue