Created
January 19, 2022 17:02
-
-
Save sylvaindesve/0e5aada4207247e249e97f265e81a052 to your computer and use it in GitHub Desktop.
Implémentation de EventEmitter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
("use strict"); | |
/** | |
* Le type des fonctions d'écoute d'un événement. | |
* | |
* @typedef Listener | |
* @type {(...unknown) => void} | |
*/ | |
/** | |
* Classe à étendre pour bénéficier d'un mécanisme d'émission et d'écoute | |
* d'événement. | |
* | |
* @example | |
* ``` | |
* class PersonModel extends EventEmitter { | |
* #name; | |
* | |
* constructor(name) { | |
* super(); | |
* this.#name = name; | |
* } | |
* | |
* get name() { | |
* return this.#name; | |
* } | |
* | |
* set name(newName) { | |
* const oldName = this.name; | |
* this.#name = newName; | |
* this.emit("change", "name", newName, oldName, this); | |
* } | |
* } | |
* | |
* class PersonView { | |
* #model; | |
* | |
* constructor(model) { | |
* this.#model = model; | |
* model.on("change", (attribute, newValue, oldValue, model) => { | |
* console.log( | |
* `attribute ${attribute} has changed from ${oldValue} to ${newValue}` | |
* ); | |
* this.render(); | |
* }); | |
* } | |
* | |
* render() { | |
* // Fonction de rendu | |
* } | |
* } | |
* ``` | |
*/ | |
export class EventEmitter { | |
constructor() { | |
/** | |
* Dictionnaire des écouteurs d'événement par nom d'événement. | |
* | |
* @type {{[eventName: string]: Listener[]}} | |
*/ | |
this.listeners = {}; | |
} | |
/** | |
* Ajouter un écouteur pour l'événement indiqué. | |
* | |
* @param {string} eventName Le nom de l'événement | |
* @param {Listener} listener La fonction a appeler lorsque l'événement survient | |
* @returns {() => void} Une fonction permettant de retirer l'écoute | |
*/ | |
on(eventName, listener) { | |
if (typeof this.listeners[eventName] !== "object") { | |
this.listeners[eventName] = []; | |
} | |
this.listeners[eventName].push(listener); | |
return () => this.removeListener(eventName, listener); | |
} | |
/** | |
* Retire une fonction d'écoute pour l'événement indiqué. | |
* | |
* @param {string} eventName Le nom de l'événement | |
* @param {Listener} listener La fonction d'écoute à retirer | |
*/ | |
removeListener(eventName, listener) { | |
if (typeof this.listeners[eventName] === "object") { | |
const idx = this.listeners[eventName].indexOf(listener); | |
if (idx > -1) { | |
this.listeners[eventName].splice(idx, 1); | |
} | |
} | |
} | |
/** | |
* Emet un évenement en déclenchant toutes les fonctions d'écoute rattaché | |
* à cet événement. | |
* | |
* @param {string} eventName Le nom de l'événement | |
* @param {...unknown} args Les arguments à passer aux fonctions d'écoute | |
*/ | |
emit(eventName, ...args) { | |
if (typeof this.listeners[eventName] === "object") { | |
this.listeners[eventName].forEach((listener) => | |
listener.apply(this, args) | |
); | |
} | |
} | |
/** | |
* Ajoute un écouteur qui ne sera déclenché que sur la prochaine émission de | |
* l'événement en question puis retiré. | |
* | |
* @param {string} eventName Le nom de l'événement | |
* @param {Listener} listener La fonction d'écoute | |
*/ | |
once(eventName, listener) { | |
const remove = this.on(eventName, (...args) => { | |
remove(); | |
listener.apply(this, args); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment