Last active
April 7, 2026 21:24
-
-
Save nathnolt/260fccc5f9f2aed143336b68c7f07714 to your computer and use it in GitHub Desktop.
small 325 bytes JS event system with array support and priority via unshift
This file contains hidden or 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
| /** | |
| * An event system which allows arrays of events and handlers within the method calls. | |
| */ | |
| export function eventSystem() { | |
| // all as let for compacting | |
| let map = {} | |
| let getFlattenedArray = (x) => [x].flat(Infinity) | |
| // For futher compacting | |
| let arr | |
| let event | |
| let handler | |
| let index | |
| /** | |
| * @typedef { ({type: string, data: unknown}) => void } handler | |
| */ | |
| return { | |
| /** | |
| * Listen to events | |
| * @param {string|string[]} events - Which event(s) to listen to | |
| * @param {handler|handler[]} handlers - What handlers handle these events | |
| * @param {boolean} unshift - When truthy: Execute these handlers first | |
| */ | |
| on(events, handlers, unshift) { | |
| for(event of getFlattenedArray(events)) { | |
| arr = map[event] ??= [] | |
| for(handler of getFlattenedArray(handlers)) { | |
| if(arr.indexOf(handler) == -1) { | |
| if(unshift) { | |
| arr.unshift(handler) | |
| } else { | |
| arr.push(handler) | |
| } | |
| } | |
| } | |
| } | |
| }, | |
| /** | |
| * Emit events to listeners | |
| * @param {string|string[]} events - What event(s) to emit | |
| * @param {unknown} data - What data to add | |
| */ | |
| emit(events, data) { | |
| for(event of getFlattenedArray(events)) { | |
| for(handler of map[event] ?? []) { | |
| handler({type: event, data: data}) | |
| } | |
| } | |
| }, | |
| /** | |
| * Stop listening to events | |
| * @param {string|string[]} events - What events to stop listening to | |
| * @param {undefined|handler|handler[]} handlers - What handlers to stop. When undefined, stop all handlers | |
| */ | |
| off(events, handlers) { | |
| for(event of getFlattenedArray(events)) { | |
| arr = map[event] = handlers ? map[event] : [] | |
| for(handler of getFlattenedArray(handlers)) { | |
| index = arr.indexOf(handler) | |
| if(index != -1) { | |
| arr.splice(index, 1) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| // Terser minified version (325 bytes) | |
| export function eventSystem(){let f,o,e,t,r={},n=f=>[f].flat(1/0);return{on(t,i,p){for(o of n(t))for(e of(f=r[o]??=[],n(i)))-1==f.indexOf(e)&&(p?f.unshift(e):f.push(e))},emit(f,t){for(o of n(f))for(e of r[o]??[])e({type:o,data:t})},off(i,p){for(o of n(i))for(e of(f=r[o]=p?r[o]:[],n(p)))t=f.indexOf(e),-1!=t&&f.splice(t,1)}}} | |
| // test / example code for the eventSystem | |
| { | |
| var test = eventSystem() | |
| function handler1(e) { | |
| console.log('handler1', e) | |
| } | |
| console.log('1. adding handlers for click / whatever') | |
| test.on( | |
| [ | |
| 'click', | |
| 'whatever' | |
| ], | |
| [ | |
| (e) => { | |
| console.log(e.type, e.data) | |
| }, | |
| handler1 | |
| ] | |
| ) | |
| console.log('2. emitting click') | |
| test.emit('click', {t: 200}) | |
| console.log('3. emitting whatever') | |
| test.emit('whatever', 'nice') | |
| console.log('4. removing handler1 for click') | |
| test.off('click', handler1) | |
| console.log('5. emitting click') | |
| test.emit('click', {t: 300}) | |
| console.log('6. removing all handlers for click') | |
| test.off('click') | |
| console.log('7. emitting click') | |
| test.emit('click', {t: 400}) | |
| console.log('8. emitting whatever') | |
| test.emit('whatever', {t: 500}) | |
| console.log('9. removing all handlers for whatever') | |
| test.off('whatever') | |
| console.log('10. emitting whatever') | |
| test.emit('whatever', {t: 600}) | |
| console.log('11. removing all handlers for bla') | |
| test.off('bla') | |
| console.log('12. emitting bla') | |
| test.emit('bla', {t: 700}) | |
| console.log('13. onning single') | |
| test.on('single', handler1) | |
| console.log('14. onning single2') | |
| test.on('single2', handler1) | |
| console.log('15. emitting both') | |
| test.emit(['single', 'single2'], {t: 800}) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment