OpenHausIO / backend

HTTP API for the OpenHaus SmartHome/IoT solution
https://docs.open-haus.io
6 stars 2 forks source link

Add a custom "Events" class for components? #487

Closed mStirner closed 1 month ago

mStirner commented 3 months ago

To be able to make every emitted event somewhere in a component available in all worker threads (if implemented, see #6), a custom/intercepted .emit(...) method is needed.

Either use a Proxy or a custom EventEmitter class.

Proxy approach (quick ChatGPT asked):

const EventEmitter = require('events');

// Erstellen einer neuen EventEmitter-Instanz
const myEmitter = new EventEmitter();

// Proxy-Handler erstellen
const handler = {
    apply: function(target, thisArg, argumentsList) {
        const [eventName, ...args] = argumentsList;
        console.log(`Event emitted: ${eventName}`, args);
        // Aufruf der originalen emit-Methode
        return Reflect.apply(target, thisArg, argumentsList);
    }
};

// Proxy für die emit-Methode erstellen
myEmitter.emit = new Proxy(myEmitter.emit, handler);

// Beispielereignisse
myEmitter.emit('event1', 'data1');
myEmitter.emit('event2', { key: 'value' });
myEmitter.emit('event3', 42);

EventEmitter class approach (quick written here)

class Events extends EventEmitter {

    constructor(...args) {
        super(...args);
        this._registeredEvents = new Set();
    }

    emit(event, ...args) {

        if (!this._registeredEvents.has(event)) {

            this._registeredEvents.add(event);

            process.nextTick(() => {
                super.emit("_eventRegistered", event, ...args);
            });

        }

        return super.emit(event, ...args);

    }

}
mStirner commented 2 months ago
const { EventEmitter } = require("events");

module.exports = class Events extends EventEmitter {

    constructor(...args) {
        super(...args);
    }

    static symbol = Symbol("register");
    static events = new Set();

    emit(event, ...args) {

        // is the code below even necessary?
        // if we hook into the `.emit` method
        // we could just use this here to "broadcast" into child/plugin/worker
        // change `static symbol...` to `static broadcast = Symbol("broadcast")`
        // and emit events as symbol: `super.emit(Events.broadcast, ...)`
        // some where, where the main/worker communication is handeld, listen then for `Events.on(Events.broadcast, ...)`

        if (!Events.events.has(event)) {

            Events.events.add(event);

            process.nextTick(() => {
                super.emit(Events.symbol, event, ...args);
            });

        }

        return super.emit(event, ...args);

    }

};