copy Daniel's conversion of EventEmitter to TypeScript from microui

This commit is contained in:
Bruno Windels 2021-09-16 10:23:03 +02:00
parent 2396a84c99
commit cce8207870
4 changed files with 20 additions and 17 deletions

View file

@ -18,7 +18,7 @@ limitations under the License.
// as in some cases it would really be more convenient to have multiple events (like telling the timeline to scroll down) // as in some cases it would really be more convenient to have multiple events (like telling the timeline to scroll down)
// we do need to return a disposable from EventEmitter.on, or at least have a method here to easily track a subscription to an EventEmitter // we do need to return a disposable from EventEmitter.on, or at least have a method here to easily track a subscription to an EventEmitter
import {EventEmitter} from "../utils/EventEmitter.js"; import {EventEmitter} from "../utils/EventEmitter";
import {Disposables} from "../utils/Disposables.js"; import {Disposables} from "../utils/Disposables.js";
export class ViewModel extends EventEmitter { export class ViewModel extends EventEmitter {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {EventEmitter} from "../../utils/EventEmitter.js"; import {EventEmitter} from "../../utils/EventEmitter";
import {RoomSummary} from "./RoomSummary.js"; import {RoomSummary} from "./RoomSummary.js";
import {GapWriter} from "./timeline/persistence/GapWriter.js"; import {GapWriter} from "./timeline/persistence/GapWriter.js";
import {RelationWriter} from "./timeline/persistence/RelationWriter.js"; import {RelationWriter} from "./timeline/persistence/RelationWriter.js";

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {EventEmitter} from "../../utils/EventEmitter.js"; import {EventEmitter} from "../../utils/EventEmitter";
import {SummaryData, processStateEvent} from "./RoomSummary.js"; import {SummaryData, processStateEvent} from "./RoomSummary.js";
import {Heroes} from "./members/Heroes.js"; import {Heroes} from "./members/Heroes.js";
import {MemberChange, RoomMember, EVENT_TYPE as MEMBER_EVENT_TYPE} from "./members/RoomMember.js"; import {MemberChange, RoomMember, EVENT_TYPE as MEMBER_EVENT_TYPE} from "./members/RoomMember.js";

View file

@ -1,5 +1,6 @@
/* /*
Copyright 2020 Bruno Windels <bruno@windels.cloud> Copyright 2020 Bruno Windels <bruno@windels.cloud>
Copyright 2021 Daniel Fedorin <danila.fedorin@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -14,28 +15,30 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
export class EventEmitter { type Handler<T> = (value?: T) => void;
export class EventEmitter<T> {
private _handlersByName: { [event in keyof T]?: Set<Handler<T[event]>> }
constructor() { constructor() {
this._handlersByName = {}; this._handlersByName = {};
} }
emit(name, ...values) { emit<K extends keyof T>(name: K, value?: T[K]): void {
const handlers = this._handlersByName[name]; const handlers = this._handlersByName[name];
if (handlers) { if (handlers) {
for(const h of handlers) { handlers.forEach(h => h(value));
h(...values);
}
} }
} }
disposableOn(name, callback) { disposableOn<K extends keyof T>(name: K, callback: Handler<T[K]>): () => void {
this.on(name, callback); this.on(name, callback);
return () => { return () => {
this.off(name, callback); this.off(name, callback);
} }
} }
on(name, callback) { on<K extends keyof T>(name: K, callback: Handler<T[K]>): void {
let handlers = this._handlersByName[name]; let handlers = this._handlersByName[name];
if (!handlers) { if (!handlers) {
this.onFirstSubscriptionAdded(name); this.onFirstSubscriptionAdded(name);
@ -44,27 +47,27 @@ export class EventEmitter {
handlers.add(callback); handlers.add(callback);
} }
off(name, callback) { off<K extends keyof T>(name: K, callback: Handler<T[K]>): void {
const handlers = this._handlersByName[name]; const handlers = this._handlersByName[name];
if (handlers) { if (handlers) {
handlers.delete(callback); handlers.delete(callback);
if (handlers.length === 0) { if (handlers.size === 0) {
delete this._handlersByName[name]; delete this._handlersByName[name];
this.onLastSubscriptionRemoved(name); this.onLastSubscriptionRemoved(name);
} }
} }
} }
onFirstSubscriptionAdded(/* name */) {} onFirstSubscriptionAdded<K extends keyof T>(name: K): void {}
onLastSubscriptionRemoved(/* name */) {} onLastSubscriptionRemoved<K extends keyof T>(name: K): void {}
} }
export function tests() { export function tests() {
return { return {
test_on_off(assert) { test_on_off(assert) {
let counter = 0; let counter = 0;
const e = new EventEmitter(); const e = new EventEmitter<{ change: never }>();
const callback = () => counter += 1; const callback = () => counter += 1;
e.on("change", callback); e.on("change", callback);
e.emit("change"); e.emit("change");
@ -75,7 +78,7 @@ export function tests() {
test_emit_value(assert) { test_emit_value(assert) {
let value = 0; let value = 0;
const e = new EventEmitter(); const e = new EventEmitter<{ change: number }>();
const callback = (v) => value = v; const callback = (v) => value = v;
e.on("change", callback); e.on("change", callback);
e.emit("change", 5); e.emit("change", 5);
@ -85,7 +88,7 @@ export function tests() {
test_double_on(assert) { test_double_on(assert) {
let counter = 0; let counter = 0;
const e = new EventEmitter(); const e = new EventEmitter<{ change: never }>();
const callback = () => counter += 1; const callback = () => counter += 1;
e.on("change", callback); e.on("change", callback);
e.on("change", callback); e.on("change", callback);