event emitter - typescript
יש לממש event emitter ב typescript
EventEmitter.ts
- interface IEventMap {
- [key: string]: Function[];
- }
- class EventEmitter {
- private _eventMap: IEventMap = {};
- private _oncers: IEventMap = {};
- on(name: string, cb: Function) {
- if (!this._eventMap[name]) {
- this._eventMap[name] = [];
- }
- this._eventMap[name].push(cb);
- }
- emit(name: string, ...args: any[]) {
- const callbacks = this._eventMap[name];
- if (callbacks) {
- for (const cb of callbacks) {
- cb(...args); //call all registered callbacks
- }
- }
- const funcs = this._oncers[name];
- if (funcs) {
- for (const cb of funcs) {
- cb(...args); //call all registered callbacks
- }
- delete this._oncers[name]; //ensure they are not called again
- }
- }
- off(name: string, cb: Function) {
- let callbacks = this._eventMap[name];
- if (callbacks) {
- // callbacks = callbacks.filter(func=> func !== cb);
- let i = callbacks.findIndex((item) => item === cb);
- callbacks.splice(i, 1);
- }
- }
- once(name: string, cb: Function) {
- if (!this._oncers[name]) {
- this._oncers[name] = [];
- }
- this._oncers[name].push(cb);
- }
- listeners(name: string) {
- return [...this._eventMap[name], ...this._oncers[name]];
- }
- eventNames() {
- return [...Object.keys(this._eventMap), ...Object.keys(this._oncers)];
- }
- removeAllListeners(name: string) {
- delete this._eventMap[name];
- delete this._oncers[name];
- }
- }
- export default EventEmitter;
Clock.ts
- import EventEmitter from "./EventEmitter";
- export enum ClockEvents {
- TICK = "TICK",
- STARTED = "STARTED",
- STOPPED = "STOPPED"
- }
- export class Clock extends EventEmitter {
- ms = 1000;
- count = 0;
- intervalID = 0;
- constructor(ms = 1000) {
- super();
- this.ms = ms;
- }
- start() {
- this.intervalID = setInterval(() => {
- this._tick();
- }, this.ms);
- this.emit(ClockEvents.STARTED, this.count);
- }
- stop() {
- clearInterval(this.intervalID);
- this.emit(ClockEvents.STOPPED, this.count);
- }
- private _tick() {
- this.count++;
- this.emit(ClockEvents.TICK, this.count);
- }
- }
Index.ts.ts
- import { Clock, ClockEvents } from "./Clock";
- let rolex = new Clock(500);
- rolex.on(ClockEvents.TICK, (count: number) => {
- console.log(`ticking rolex ${count} times`);
- if (count >= 5) {
- rolex.stop();
- }
- });
- rolex.once(ClockEvents.STARTED, (count: number) => {
- console.log(`rolex started at ${count} count`);
- requestAnimationFrame(() => {
- console.log("on start - rolex.eventNames", rolex.eventNames());
- });
- });
- rolex.once(ClockEvents.STOPPED, async (count: number) => {
- console.log(`rolex stopped after ${count} times`);
- requestAnimationFrame(() => {
- console.log("on stop - rolex.eventNames", rolex.eventNames());
- });
- });
- console.log("rolex.eventNames", rolex.eventNames());
- rolex.start();