D
Deno

help

Migrating from EventEmitter…

Jjcayzac11/24/2023
Hi! I've got some legacy code that depends on node:events 's EventEmitter class, specifically its once() method that returns a promise resolving the next time a specific event arrives, as well as removeAllListeners(). What would you suggest I use to get rid of that dependency? I can't use EventTarget since it doesn't let you drop all the registered listeners and doesn't support the once() scenario. Anything else? I can make a small wrapper around addEventListener("name", listener, { once: true }) for the promisified once(), but not sure how to do the removeAllListeners() call with EventTarget. In the REPL I can see there is some listeners object under [Symbol()] but I have no idea how to acces it.
DAHDeno AI Helper11/24/2023
Based on the documentation, Deno's EventTarget indeed does not provide a removeAllListeners() equivalent or a once() method that returns a promise. However, you can achieve similar functionality with a bit of extra code. For the once() method, you can create a new Promise and resolve it inside the event listener. After the event is fired, you can remove the listener. Here's an example:
function once(target, type) {
return new Promise((resolve) => {
const listener = (event) => {
resolve(event);
target.removeEventListener(type, listener);
};
target.addEventListener(type, listener);
});
}

const target = new EventTarget();
once(target, "foo").then((event) => console.log(event));
target.dispatchEvent(new Event("foo"));
function once(target, type) {
return new Promise((resolve) => {
const listener = (event) => {
resolve(event);
target.removeEventListener(type, listener);
};
target.addEventListener(type, listener);
});
}

const target = new EventTarget();
once(target, "foo").then((event) => console.log(event));
target.dispatchEvent(new Event("foo"));
As for the removeAllListeners() method, there isn't a direct equivalent in the EventTarget interface. However, you can keep track of your listeners and remove them manually when needed. Here's an example:
const listeners = new Map();

function addListener(target, type, listener) {
target.addEventListener(type, listener);
if (!listeners.has(type)) {
listeners.set(type, new Set());
}
listeners.get(type).add(listener);
}

function removeAllListeners(target, type) {
if (listeners.has(type)) {
for (const listener of listeners.get(type)) {
target.removeEventListener(type, listener);
}
listeners.get(type).clear();
}
}

const target = new EventTarget();
addListener(target, "foo", () => console.log("foo"));
addListener(target, "foo", () => console.log("bar"));
removeAllListeners(target, "foo");
const listeners = new Map();

function addListener(target, type, listener) {
target.addEventListener(type, listener);
if (!listeners.has(type)) {
listeners.set(type, new Set());
}
listeners.get(type).add(listener);
}

function removeAllListeners(target, type) {
if (listeners.has(type)) {
for (const listener of listeners.get(type)) {
target.removeEventListener(type, listener);
}
listeners.get(type).clear();
}
}

const target = new EventTarget();
addListener(target, "foo", () => console.log("foo"));
addListener(target, "foo", () => console.log("bar"));
removeAllListeners(target, "foo");
Please note that these are not direct replacements and might not cover all use cases of the original EventEmitter methods. Also, this information is not
DAHDeno AI Helper11/24/2023
explicitly stated in the documentation, but it's a general approach to achieve similar functionality. 🦕
Jjcayzac11/24/2023
AI bot has the first example wrong. There's no need to call removeEventListener if you use addEventListener(type, listener, { once: true}). Also this doesn't handle abort signals...

Looking for more? Join the community!