Skip to content

Instantly share code, notes, and snippets.

@jim-clark
Last active August 29, 2015 14:24
Show Gist options
  • Select an option

  • Save jim-clark/814800d2070202408fcb to your computer and use it in GitHub Desktop.

Select an option

Save jim-clark/814800d2070202408fcb to your computer and use it in GitHub Desktop.
MEAN with Socket.IO

Adding Realtime to our MEAN Stack Application


Learning Objectives


  • Add realtime event-based communication between client and server in a MEAN Stack app

Roadmap

  • Intro to Socket.IO

  • Setting up Socket.IO

  • Our new feature: Hippo Chat

  • Code the UI

  • Frontend Realtime Code

  • Backend Realtime Code


Intro to Socket.IO

  • The HTTP protocol does not enable bidirectional realtime communication.

  • Fortunately, HTML5 included a new protocol that does - websockets.

  • Socket.IO is a JavaScript library that makes realtime bidirectional event-based communication easier than working with websockets directly.

  • It even works in older browsers without websockets by simulating it using old dinosaur techniques.


Socket.IO - Basic Architecture


  • Clients can send a message to the server which in turn can push messages to all clients "listening" on the same channel.

Setting up Socket.IO


Both the client and server need to be configured with Socket.IO.


Config the Server


  • Install the Socket.IO Module

     ? npm install socket.io --save
    
  • We're going to keep our Socket.IO code in a separate file. Create a file named io.js in our project's root folder.

  • Socket.IO needs to mount to the http server, not the Express server. We will require our new io.js module in the /bin/www file:

     var server = http.createServer(app);
     // insert new code below the above line
     var io = require('../io');
     io.attach(server);

Config the Server (cont.)


  • With our io.js now loaded, let's put some test code in it:

     var io = require('socket.io')();
     
     io.on('connection', function (socket) {
     	console.log('socket.io connected');
     });
     
     module.exports = io;
  • Time to move on to the client...


Config the Client (browser)

  • In our index.ejs file, we will need to include a special script file that is generated by the socket.io module on the server:

     <!-- existing HTML above -->
     	<script src="/socket.io/socket.io.js"></script>
     	<script>
         	var socket = io();
         	console.log(socket);
     	</script>
     </body>
  • The socket.io.js script exposes an io global function that we executed to obtain our connection to the server which we then assigned to a variable named socket.

  • Browse to localhost:3000 and check that the Socket object logged in the console has a connected: true property.


Our new feature: Hippo Chat

  • We want to add a realtime Chat feature that allows all users connected to the same server to chat with each other.

  • We will need to add some new UI below the Add a Hippo section in the index.ejs file:

    • A <hr> tag for a little visual separation.
    • Two <input> elements, one for the message, the other for the user's name.
    • A Button to send the message.
    • A <div> that will hold a Bootstrap styled List Group. Each List Item will be a message.

Code the UI

  • This Gist contains the HTML to add to index.ejs.

  • Review the HTML.

  • Note the use of a ng-repeat to stamp out a Bootstrap styled template for each message in the messages array.

  • We will add the messages array and other code in our AngularJS controller next...


Frontend Realtime Code

  • What do we need the code to do in our Angular controller?

  • Pseudocode it.


Frontend Realtime Code

  • We need code to display messages:

    • Initialize the messages array to an empty array.
    • "Listen" for new messages originating from other browsers.
    • When a new message is received, put it in the beginning of the of the array so that recent messages display first in the ng-repeat.
  • We need code to send a message when the Send Message button is clicked:

    • Push our message to the server and include a JS object with two properties - what are they?
    • Clear the new message <textarea>.

Frontend Realtime Code


Add this code to the HomeController

$scope.messages = [];

// listen for a 'new message' event of the socket object
socket.on('new message', function(msg) {
	$scope.$apply(function () {
   		$scope.messages.unshift(msg);
	});
});

// push a new message to the server
$scope.sendMsg = function() {
	socket.emit('new message', {user: $scope.username, message: $scope.newMsg});
	$scope.newMsg = '';
};

Backend Realtime Code


This is all the code that needs to be in the io.js file:

var io = require('socket.io')();

io.on('connection', function (socket) {
    socket.on('new message', function(msg) {
        io.emit('new message', msg);
    });
});

module.exports = io;

Backend Realtime Code

  • Socket.IO (io) on the server sends a message to all connected clients, including the sending client, using the emit() method.

  • The io object is the server, and the socket would represent a particular client (browser).

  • We have only scratched the surface of Socket.IO's capabilities. It has the concept of namespacing and rooms for more granular control of messages.

  • If you are interested in learning more, be sure to check the docs!


Realtime Is Fun!


Challenges


Challenge 1


Disable the Send Message button

  • Disable the Send Message button if there is:
    • No name entered for the user
    • An empty message

Challenge 2


Add Message Pesistence

  • Currently, if we refresh our browser, we lose our chat history.

  • Use Mongoose & MongoDB to persist recent chat messages.


Challenge 3


Limit Chat Data

  • Limit the amount of chat messages persisted to a maximum of 20 messages.

References


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment