MooTools object messaging

Events

In JavaScript, we often tend to use events all over the place. In MooTools, the custom ‘domready’ event is particularly prevalent. However, events suffer from a few drawbacks:

You can’t attach events to non-existent objects.

Pretty self-explanatory, really. What this means in practice, though, is that you can’t easily let object A know when object B exists.

If an object starts to listen for an event after it’s already fired, it’ll never hear it.

Because content on the web isn’t always delivered in perfect order (especially when you’re loading scripts synchronously), it’s possible for an object to try to listen for an event after it’s already been fired. Obviously, this means that your listener object will never run the code that’s dependent on that event, which could be Bad Thing™.

It’s not particularly easy to know which object is listening for which events.

There are ways around this, but you can’t just dir() the listeners in Firebug.

A messaging system

For all of these reasons (and probably a few more that I’ve forgotten about), a messaging system can be an invaluable addition to your arsenal when writing JavaScript. How does a messaging system work? Well, interested objects ‘register’ themselves as listeners for particular message ‘handles’, and other objects can send messages using those ‘handles’. Below is a very simple MooTools messaging system that I knocked up, which has a few cool features, including:

  • When you register() a listener, you can have its callback immediately fire if that message has ever been sent before.
  • You can very easily see which callbacks are associated with which messages by simply dir()-ing the ‘listeners’ member.
  • You can unregister() a listener at any time (provided you’ve got a reference to the function and the handle).
  • Handles can be any valid JavaScript type — Strings, Numbers, even Objects.

Feel free to use and extend this system — as I mentioned, this is a very simple system. If you do extend it, let me know in the comments!

Let me know what you think about this system in the comments.

[sourcecode language=”javascript”]
barryvan.base.Messaging = new Class({
listeners: $H(),
sentMessages: [],

initialize: function() {

},

/**
* Register a listener for a particular handle.
* handle [String]: The message ‘handle’ to listen for.
* callback [Function]: The function to be called when the handle is sent a message. The contents of the messages will be included in the function call.
* dontCheck [Boolean]: If falsey and the handle has had a message sent to it, immediately call the callback function (without contents), and continue to add the listener as normal.
*/
register: function(handle, callback, dontCheck) {
if ($type(callback) !== ‘function’) return;

if (!dontCheck && this.sentMessages[handle]) {
callback();
}

if (!this.listeners.has(handle)) this.listeners[handle] = [];
this.listeners[handle].push(callback);
},

/**
* Unregister a listener for a particular handle.
* handle [String]: The message ‘handle’ to cease listening for.
* callback [Function]: The function which was earlier assigned as the callback for the messages.
*/
unregister: function(handle, callback) {
if (this.listeners.has(handle)) {
this.listeners[handle].erase(callback);
}
},

/**
* Send a message to the given handle with the given contents — send the contents to all the registered listeners for that handle.
* handle [String]: The message ‘handle’ to transmit to.
* contents [Mixed]: The contents to be sent to the listeners.
*/
send: function(handle, contents) {
this.sentMessages.include(handle);
if (this.listeners.has(handle)) {
this.listeners[handle].each(function(callback) {
callback(contents);
});
}
}
});
[/sourcecode]

Comments

2 responses to “MooTools object messaging”

  1. Nicholas Avatar

    Looks good, Barry. Question: you say,
    When you register() a listener, you can have its callback immediately fire if that message has ever been sent before.
    What exactly do you mean by “ever”? Could there ever be a case where the lifetime of the message manager is such that this would cause messages to fire that are no longer valid or appropriate?

  2. Nicholas Avatar

    Oh, and what about the possibility of broadcasting messages to a variety of sinks?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.