Skip to content

Instantly share code, notes, and snippets.

@JasonKleban
Last active January 26, 2023 06:33
Show Gist options
  • Star 36 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save JasonKleban/50cee44960c225ac1993c922563aa540 to your computer and use it in GitHub Desktop.
Save JasonKleban/50cee44960c225ac1993c922563aa540 to your computer and use it in GitHub Desktop.
TypeScript LiteEvent Events implementation
interface ILiteEvent<T> {
on(handler: { (data?: T): void }) : void;
off(handler: { (data?: T): void }) : void;
}
class LiteEvent<T> implements ILiteEvent<T> {
private handlers: { (data?: T): void; }[] = [];
public on(handler: { (data?: T): void }) : void {
this.handlers.push(handler);
}
public off(handler: { (data?: T): void }) : void {
this.handlers = this.handlers.filter(h => h !== handler);
}
public trigger(data?: T) {
this.handlers.slice(0).forEach(h => h(data));
}
public expose() : ILiteEvent<T> {
return this;
}
}
class Security{
private readonly onLogin = new LiteEvent<string>();
private readonly onLogout = new LiteEvent<void>();
public get LoggedIn() { return this.onLogin.expose(); }
public get LoggedOut() { return this.onLogout.expose(); }
// ... onLogin.trigger('bob');
}
function Init() {
var security = new Security();
var loggedOut = () => { /* ... */ }
security.LoggedIn.on((username?) => { /* ... */ });
security.LoggedOut.on(loggedOut);
// ...
security.LoggedOut.off(loggedOut);
}
@wonea
Copy link

wonea commented Nov 3, 2016

Brilliance!

@ziuniecki
Copy link

Simple and clear. Nice :)

@Rene-Sackers
Copy link

Beautiful. Thank you.

Copy link

ghost commented Feb 10, 2018

good work!

@zbigniew-gajewski
Copy link

Thanks!

@JasonKleban
Copy link
Author

JasonKleban commented Apr 11, 2019

Made a stricter version here, getting rid of optionality of data?: T in various signatures without impacting the case where T is void and should overall require no data parameter: https://gist.github.com/JasonKleban/924babb9c56d697c2d2a8f6f604eb3d4. I didn't want to revise this version because that version might turn out to have some negative qualities.

@maucaro
Copy link

maucaro commented Feb 14, 2021

This was super helpful Jason, thank you! I do have one question: why do you use this.handlers.slice(0).forEach instead of just this.handlers.forEach?

@JasonKleban
Copy link
Author

@maucaro in case one of the earlier handlers modifies the handlers array in the handling of a particular event. It's just the saner general approach, but I guess you can adjust this for your situation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment