fix: remove event listeners correctly

This commit is contained in:
Oscar Lorentzon 2021-06-02 23:04:16 +02:00
parent bdba74d026
commit 0d904a641b
2 changed files with 91 additions and 16 deletions

View File

@ -1,5 +1,5 @@
export class EventEmitter {
private _events: { [type: string]: ((event: any) => void)[] };
private _events: { [type: string]: ((event: any) => void)[]; };
constructor() { this._events = {}; }
@ -29,16 +29,14 @@ export class EventEmitter {
handler: (event: T) => void): void {
if (!type) { this._events = {}; return; }
if (!this._listens(type)) {
if (this._listens(type)) {
const index = this._events[type].indexOf(handler);
if (index >= 0) {
this._events[type].splice(index, 1);
}
if (this._events[type].length) {
if (!this._events[type].length) {
delete this._events[type];
}
} else {
delete this._events[type];
}
}
@ -49,8 +47,8 @@ export class EventEmitter {
type: string,
event: T): void {
if (!this._listens(type)) { return; }
for (let fn of this._events[type]) {
fn.call(this, event);
for (const handler of this._events[type]) {
handler(event);
}
}

View File

@ -1,17 +1,20 @@
import { EventEmitter } from "../../src/util/EventEmitter";
describe("EventEmitter", () => {
describe("EventEmitter.ctor", () => {
test("should be defined", () => {
const eventEmitter = new EventEmitter();
expect(eventEmitter).toBeDefined();
});
});
describe("EventEmitter.on", () => {
let eventEmitter: EventEmitter;
beforeEach(() => {
eventEmitter = new EventEmitter();
});
it("should be defined", () => {
expect(eventEmitter).toBeDefined();
});
it("should emit on event", (done: Function) => {
test("should emit on event", (done: Function) => {
let data: string = "testdata";
eventEmitter.on("test", (ev: any) => {
@ -22,7 +25,7 @@ describe("EventEmitter", () => {
eventEmitter.fire("test", data);
});
it("should get two different events only once", (done: Function) => {
test("should get two different events only once", (done: Function) => {
let data: string = "testdata";
let data2: string = "testdata2";
@ -45,7 +48,7 @@ describe("EventEmitter", () => {
eventEmitter.fire("test2", data2);
});
it("should get the same event twice", (done: Function) => {
test("should get the same event twice", (done: Function) => {
let data: string = "testdata";
let i: number = 0;
@ -65,5 +68,79 @@ describe("EventEmitter", () => {
eventEmitter.fire("test", data);
});
});
interface TestEvent {
data: string;
type: string;
}
describe("EventEmitter.off", () => {
let eventEmitter: EventEmitter;
beforeEach(() => {
eventEmitter = new EventEmitter();
});
test("should remove listener", () => {
const event: TestEvent = { data: "testdata", type: "test" };
let onTestCount = 0;
const onTest = () => {
onTestCount++;
fail();
};
eventEmitter.on(event.type, onTest);
eventEmitter.off(event.type, onTest);
eventEmitter.fire(event.type, event);
expect(onTestCount).toBe(0);
});
test("should remove specific listener", () => {
const event: TestEvent = { data: "testdata", type: "test" };
let count = 0;
const onTest1 = () => {
count++;
fail();
};
const onTest2 = (e: TestEvent) => {
count++;
expect(e.type).toBe("test");
expect(count).toBe(1);
};
eventEmitter.on(event.type, onTest1);
eventEmitter.on(event.type, onTest2);
eventEmitter.off(event.type, onTest1);
eventEmitter.fire(event.type, event);
expect(count).toBe(1);
});
test("should remove all listeners", () => {
const event: TestEvent = { data: "testdata", type: "test" };
let count = 0;
const onTest1 = () => {
count++;
fail();
};
const onTest2 = () => {
count++;
fail();
};
eventEmitter.on(event.type, onTest1);
eventEmitter.on(event.type, onTest2);
eventEmitter.off(event.type, onTest1);
eventEmitter.off(event.type, onTest2);
eventEmitter.fire(event.type, event);
expect(count).toBe(0);
});
});