1

I'm writing a small library that essentially polls a site for data, and is then supposed to notify a consumer when it matches. In C# I'd use events, which are actually multicast delegates. I've written my own multicast delegate in javascript before, but I figure there has to be a better way.

A consumer should register a callback which should be called when data is available. Something like this:

window.MyLibrary.dataAvailable(function(data) {
    // do something with data
});

In the background MyLibrary is polling for data. When it finally has something that matches, it should execute the registered function(s). Multiple functions should be able to be registered and probably unregistered too.

CustomEvent is very very close to what I want. The problem with CustomEvent is that the event has to be raised on an element - it can't be raised on an object. That is, this wouldn't work:

var event = new CustomEvent('dataAvailable', { data: 'dynamic data' });

window.MyLibrary.addEventListener('dataAvailable', function (e) { 
    // do something with e.data
}, false);

// From somewhere within MyLibrary
this.dispatchEvent(event, data);

How do you register handlers on objects in javascript? I need to support the usual browsers and IE11+. Ideally I wouldn't be pulling in a library to do any of this. jQuery will be available on the page and can be used if that would make things easier.

For reference, this is the Multicast Delegate implementation I've used in the past:

function MulticastDelegate(context) {
    var obj = context || window,
        handlers = [];

    this.event = {
        subscribe: function (handler) {
            if (typeof (handler) === 'function') {
                handlers.push(handler);
            }
        },
        unsubscribe: function (handler) {
            if (typeof (handler) === 'function') {
                handlers.splice(handlers.indexOf(handler), 1);
            }
        }
    };

    this.execute = function () {
        var args = Array.prototype.slice.call(arguments);
        for (var i = 0; i < handlers.length; i++) {
            handlers[i].apply(obj, args);
        }
    };
}

var myEvent = new MulticastDelegate();
myEvent.event.subscribe(function(data) { ... }); // handler 1
myEvent.event.subscribe(function(data) { ... }); // handler 2
myEvent.execute(some_data);
Josh Smeaton
  • 47,939
  • 24
  • 129
  • 164
  • elements are objects, why not use an element? – dandavis Jun 22 '16 at 06:57
  • 1
    Because it seems messy. Why should I have to proxy data through an element on the page when it's simply one piece of javascript talking to another piece of javascript. I *can* go via an element, but I'd prefer not to if there's a better way. Also, the API isn't as nice. "Here, wait for some data I'm going to send you.. just bind to this magic string on `window`". – Josh Smeaton Jun 22 '16 at 06:58
  • core doesn't provide events, browsers do, and jq makes it very flexible with delegation, once(), namespaces, etc. you can code your own EE in a few lines of core, adding features as you need them, but one of http://microjs.com/#events probably already has what you would code... – dandavis Jun 22 '16 at 07:01
  • @dandavis thanks, the microjs page led me to https://api.jquery.com/jQuery.Callbacks/ which seems to be what I want. – Josh Smeaton Jun 22 '16 at 07:06

0 Answers0