JAVASCRIPT
Binary Search Tree
Insert, search, and delete while keeping values sorted. Average O(log n), worst O(n) if the tree becomes a chain.
Subscribe a listener to an event and call it on emit by priority. once runs a single time.
class EventEmitter {
constructor() {
this.events = new Map();
}
on(event, listener, priority = 0) {
return this.add(event, listener, priority, false);
}
once(event, listener, priority = 0) {
return this.add(event, listener, priority, true);
}
off(event, listener) {
const list = this.events.get(event);
if (!list) {
return this;
}
if (listener == null) {
this.events.delete(event);
return this;
}
const next = list.filter((entry) => entry.listener !== listener);
if (next.length) {
this.events.set(event, next);
} else {
this.events.delete(event);
}
return this;
}
emit(event, ...args) {
const list = this.events.get(event);
if (!list || list.length === 0) {
return false;
}
const snapshot = list.slice();
for (const entry of snapshot) {
if (entry.once) {
this.drop(event, entry);
}
entry.listener(...args);
}
return true;
}
listenerCount(event) {
return this.events.get(event)?.length ?? 0;
}
add(event, listener, priority, once) {
if (typeof listener !== 'function') {
throw new TypeError('listener must be a function.');
}
const list = this.events.get(event) ?? [];
const entry = { listener, priority, once };
const index = list.findIndex((item) => item.priority < priority);
if (index === -1) {
list.push(entry);
} else {
list.splice(index, 0, entry);
}
this.events.set(event, list);
return this;
}
drop(event, entry) {
const list = this.events.get(event);
if (!list) {
return;
}
const next = list.filter((item) => item !== entry);
if (next.length) {
this.events.set(event, next);
} else {
this.events.delete(event);
}
}
}
const bus = new EventEmitter();
const profile = (user) => console.log('profile', user.id);
bus.on('user.created', profile, 1);
bus.once('user.created', (user) => {
console.log('welcome', user.id);
}, 10);
bus.emit('user.created', { id: 7 });
bus.emit('user.created', { id: 7 }); // once does not run again
bus.off('user.created', profile);
A practical place for this snippet in a real project.
Useful for notifying separate parts of a page after a user is created. It is not a message bus between servers.
Insert, search, and delete while keeping values sorted. Average O(log n), worst O(n) if the tree becomes a chain.
Wrap a function and reuse its result for the same inputs. The next call with the same values skips the work.
Keep a fixed number of entries and evict the least recently used item when the cache is full.
Describe the problem or idea, and I will see if it belongs in the library.