• Categories
    • Unread
    • Recent
    • Popular
    • Users
    • Groups
    • Register
    • Login

    How the shoutbox client sockets work

    Scheduled Pinned Locked Moved Development and Coding
    1 Posts 1 Posters 723 Views 1 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • SchamperS Offline
      Schamper
      last edited by

      This is about the following file: sockets.js

      We need more posts, why not write something about how the shoutbox works? Could be interesting for some people I suppose :P

      The fun thing about the recent refactor of the client sockets is that you can call them by simple doing Shoutbox.sockets.<action>(data, callback);. This is possible because we add each message to the global Shoutbox.sockets object. Doing this for every single message would take a lot of time and code, especially with the recent addition of commands. So how do we do this?

      As you can see at the beginning of the file there are 2 objects with a bunch of method names as key and socket events as value, these names will later be used as the <action>:

      	var Messages = {
      		getShouts: 'plugins.shoutbox.get',
      		sendShout: 'plugins.shoutbox.send',
      		removeShout : 'plugins.shoutbox.remove',
      		editShout: 'plugins.shoutbox.edit',
      		notifyStartTyping: 'plugins.shoutbox.notifyStartTyping',
      		notifyStopTyping: 'plugins.shoutbox.notifyStopTyping',
      		getOriginalShout: 'plugins.shoutbox.getOriginalShout',
      		saveSettings: 'plugins.shoutbox.saveSetting',
      		getSettings: 'plugins.shoutbox.getSettings',
      		getUsers: 'user.loadMore',
      		getUserStatus: 'user.isOnline'
      	};
      
      	var Events = {
      		onUserStatusChange: Messages.getUserStatus,
      		onReceive: 'event:shoutbox.receive',
      		onDelete: 'event:shoutbox.delete',
      		onEdit: 'event:shoutbox.edit',
      		onStartTyping: 'event:shoutbox.startTyping',
      		onStopTyping: 'event:shoutbox.stopTyping'
      	};
      

      These are the default messages and events we work with. Extra events or messages required for commands etc are defined by the command itself (we get to this later).

      After that we have a Handlers object, which essentially has all the default socket handlers required for the shoutbox to actually work. You can see some basic stuff ilke onReceive, onDelete etc. You can pretty much guess by their name what their function is. Interesting here is the defaultSocketHandler:

      	var Handlers = {
      		onReceive: ...,
      		onDelete: ...,
      		onEdit: ...,
      		onUserStatusChange: ..,
      		onStartTyping: ...,
      		onStopTyping: ...,
      		defaultSocketHandler: function(message) {
      			this.message = message;
      			var self = this;
      
      			return function (data, callback) {
      				if (typeof data === 'function') {
      					callback = data;
      					data = null;
      				}
      
      				socket.emit(self.message, data, callback);
      			};
      		}
      	};
      

      In the next bit I explain how the defaultSocketHandler works.

      At the very end of the file we find what we actually “expose” to the public/global Shoutbox object.

      	Shoutbox.sockets = {
      		messages: Messages,
      		events: Events,
      		registerMessage: function(handle, message) {
      			if (!Shoutbox.sockets.hasOwnProperty(handle)) {
      				Shoutbox.sockets[handle] = new Handlers.defaultSocketHandler(message);
      			}
      		},
      		registerEvent: function(event, handler) {
      			if (socket.listeners(event).length === 0) {
      				socket.on(event, handler);
      			}
      		},
      		initialize: function() {
      			for (var e in Events) {
      				if (Events.hasOwnProperty(e)) {
      					this.registerEvent(Events[e], Handlers[e]);
      				}
      			}
      
      			for (var m in Messages) {
      				if (Messages.hasOwnProperty(m)) {
      					this.registerMessage(m, Messages[m]);
      				}
      			}
      		}
      	};
      

      The first two keys, messages and events simply expose the default messages and events that we talked about at the beginning. registerMessage is more interesting. Let’s take a closer look at it.

      		registerMessage: function(handle, message) {
      			if (!Shoutbox.sockets.hasOwnProperty(handle)) {
      				Shoutbox.sockets[handle] = new Handlers.defaultSocketHandler(message);
      			}
      		},
      

      registerMessage first checks if we don’t already have the requested key in the Shoutbox.sockets object, if we don’t it adds a new key with a new defaultSocketHandler as value. We pass the message from the second argument to the defaultSocketHandler constructor, which, if you scroll up, is stored in the newly created object with this.message = message;. If you look at the return value of defaultSocketHandler you can see that it returns a function that takes 2 arguments. This function essentially just emits a socket message with the data and callback as arguments. Because we store this newly created function as the value of the Shoutbox.sockets[handle] key, this allows us to do the Shoutbox.sockets.<action>(data, callback); from the beginning of this post.

      registerEvent just registers a new event with socket.io for the passed in event and handler.

      intialize simply loops over all the Events and Messages and calls the appropriate functions to register all the default events and messages.

      Because we expose registerMessage and registerEvent commands and actions can easily add their own methods and event handlers to the Shoutbox.sockets object.

      Hopefully this post was somewhat interesting to read ;)

      1 Reply Last reply Reply Quote
      • 1 / 1
      • First post
        Last post
      Online Users