Question

I'm looking for a simple event aggregator that works with require.js. I have two modules, one containing a view model and another with a "listener" of some sort:

// view model
define(['lib/knockout-2.2.1', 'events/aggregator'], function(ko, events){

    var squareViewModel = function(contents) {
        this.click = function(){
            events.publish('squareClicked', this);
        };
    };

    return squareViewModel;
});

// some listener of some kind
define(['events/aggregator'], function(events){
    events.subscribe('squareClicked', function(e){
        alert("hurrah for events");
    });
});

Is there anything out there that does this? Is this kind of architecture even a good idea? This is my first foray into client-side architecture.

Was it helpful?

Solution

This is similar to what you posted, but I've had good luck with extending Backbone events (you don't actually have to use anything else about Backbone for this to work), something like this:

define(['underscore', 'backbone'], function( _, Backbone ) {
    var _events = _.extend({}, Backbone.Events);
    return _events;
});

And then all your viewmodels (or any code really) can use it:

define(['knockout', 'myeventbus'], function(ko, eventBus){

    return function viewModel() {
        eventBus.on('someeventname', function(newValue) { 
        // do something
        });

        this.someKOevent = function() {
            eventBus.trigger('someotherevent', 'some data');
        };

    };
});

The original idea came from this article by Derick Bailey. One of my other favorites on client-side events is this one by Jim Cowart

Again, it amounts to nearly the same thing as what you posted. However, the one thing I don't like about the approach of tying it to jQuery document DOM node is that you might have other types of events flying through there as well, bubbled up from child nodes, etc. Whereas by extended backbone events you can have your own dedicated event bus (or even more than one if you e.g. wanted to have separate data events vs. UI events).

Note regarding RequireJS in this example: Backbone and Underscore are not AMD-compatible, so you'll need to load them using a shim config.

OTHER TIPS

I ended up using jQuery to make my own:

define([], function(){
    return {

        publish: function (type, params){
            $(document.body).trigger(type, params);
        },

        subscribe: function(type, data, callback){
            $(document.body).bind(type, data, callback);
        },
    };
});

It works for what I want it for, but it has not been extensively tested.

As explunit points out in his answer, this will capture any events on document.body. I also discovered a scoping issue when accessing this inside of a passed callback function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top