July 15, 2012

Event-driven programming

Event-driven programming is an application architecture technique which suppose the existence of a main loop which is composed from two sections: event detection and event handling. This technique is very handy for programming graphical user interface, however it can lead to errors if event handlers change some values in global context and if their activity is not supervised enough in interaction with the rest of the application or other event handlers.
In JavaScript it is one of the main components that helps in developing applications, especially when working with DOM elements. There are three methods for working with events in DOM:
  •  .addEventListener(event, listener, useCapture) - for adding event listeners
  • .dispatchEvent(event) - for triggering events
  • .removeEventListener(event, listener, useCapture) - for removing event listeners
This is very good, but if we want to implement the event-driven technique in our application not only for DOM elements? We have to implement our own simple architecture by creating a EventEmitter class for simulation the same behavior like DOM elements:

    function EventEmitter() {
        // The object that will contain all the listeners
        var listeners = {};
        
        // Method to add listeners, alias: on
        this.addListener = this.on = function (event, listener) {
            if (!Array.isArray(listeners[event])) {
                listeners[event] = [];
            }
            listeners[event].push(listener);
            return this;
        };

        // Method to trigger events
        this.emit = function (event) {
            if (listeners[event]) {
                var args, i, length = listeners[event].length;
                for (i = 0; i < length; i++) {
                    args = Array.prototype.slice.call(arguments, 1)
                    listeners[event][i].apply(this, args);
                }
            }
            return this;
        };

        // Method to add a listener that will trigger only once
        this.once = function (event, listener) {
            var oneTimeListener = function () {
                listener.apply(this, arguments);
                this.removeListener(event, oneTimeListener);
            };

            this.on(event, oneTimeListener);
            return this;
        };

        // Method to remove all listeners for an event or remove all listeners for all events
        this.removeAllListeners = function (event) {
            if (event) {
                listeners[event] = [];
            } else {
                listeners = {};
            }
        };

        // Method to remove a specific listener for a specific event
        this.removeListener = function (event, listener) {
            var i, length = listeners[event].length;
            for (i = 0; i < length; i++) {
                if (listeners[event][i] == listener) {
                    listeners[event].splice(i, 1);
                    break;
                }
            }
            return this;
        };
    }

This is a Node.js like model for implementing your own event-driven architecture, it is simple in understanding and using, other classes can inherit from EventEmitter and all their instances will have these methods and can act like DOM elements, you can create your own events and attach to them some listeners, somewhere in the application you can trigger these events using ".emit()" method.

No comments:

Post a Comment