Lección 19 · 19 de 20
Eventos con EventEmitter · JavaScript
Comunique partes de un programa en Node con EventEmitter: emit, on, once, varios oyentes y el evento especial error.

EventEmitter, del módulo events de Node, implementa el patrón publicar/suscribir: un objeto anuncia que algo ha pasado y quien esté interesado reacciona, sin que uno conozca al otro. Shop hereda de EventEmitter y, en buy(), emite order cuando hay venta o soldout cuando no quedan existencias.
`on(evento, función)` registra un oyente. Un mismo evento puede tener varios: uno anota el pedido y otro avisa al almacén cuando left llega a cero. Los argumentos que se pasan a `emit` (aquí, un objeto; en soldout, el artículo y el cliente) llegan tal cual a cada oyente.
Los oyentes se ejecutan de forma síncrona y en el orden en que se registraron, dentro de la propia llamada a emit. `once` registra uno que se ejecuta solo la primera vez y después se elimina, por eso first order of the day! sale una vez y listenerCount("order") vale 2 al final.
El evento `error` es especial: si se emite y nadie lo escucha, Node lanza el error, y si no se captura, el programa termina. Por eso conviene registrar siempre un oyente de error. Este patrón está en todo Node (servidores, flujos, procesos) y también en Electron, uno de los destinos de DMarlon Studio, donde la ventana y el proceso principal se comunican con eventos.
Código · main.js
const EventEmitter = require("events");// A class that extends EventEmitter can announce what happens inside it.class Shop extends EventEmitter { constructor(stock) { super(); this.stock = stock; } buy(customer, item) { if (!this.stock[item]) return this.emit("soldout", item, customer); this.stock[item] -= 1; this.emit("order", { customer, item, left: this.stock[item] }); }}const shop = new Shop({ mug: 2 });shop.on("order", (o) => console.log(`Order: ${o.customer} bought a ${o.item}`));shop.on("order", (o) => o.left === 0 && console.log(` warehouse: restock ${o.item}`));shop.once("order", () => console.log(" first order of the day!"));shop.on("soldout", (item, who) => console.log(`Sorry ${who}, the ${item} is sold out`));shop.buy("Ana", "mug");shop.buy("Luis", "mug");shop.buy("Marta", "mug");console.log("Listeners for order:", shop.listenerCount("order"));// "error" is special: emitting it with no listener throws.try { shop.emit("error", new Error("payment gateway down"));} catch (err) { console.log("Nobody listened:", err.message);}shop.on("error", (err) => console.log("Logged:", err.message));shop.emit("error", new Error("payment gateway down"));Salida · node main.js
Order: Ana bought a mug first order of the day! Order: Luis bought a mug warehouse: restock mug Sorry Marta, the mug is sold out Listeners for order: 2 Nobody listened: payment gateway down Logged: payment gateway down
Para recordar
emitanuncia un evento con sus datos;onlo escucha.- Los oyentes se ejecutan de forma síncrona, en orden de registro.
onceescucha solo la primera vez.- Un evento
errorsin oyente lanza una excepción.
Ejercicio
Añada un evento lowstock que se emita cuando queden menos de 2 unidades de un artículo, y use off con una función con nombre para quitar el oyente del almacén después de la primera reposición.