Building a functional chat app based on Node.js (2)

Web Sockets

Web Sockets are a much more responsive technology, since they keep a connection directly open at all times for each client. This allows either the client or server to directly notify each other when changes occur on their side. In contrast to the request / response model, the server does not wait for a request before responding. We will use the package socket.io to finish up the chat app.

First, remove the code in script.js and server.js that had to do with either POST requests or polling, since they will not be necessary anymore. (You could store them in a different file for reference).

Next, there are a few number of things we need to do to set up sockets:

  1. Add the following line to index.html right above the existing "script" tag

    <script
    src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js">
    </script>

    This line will simply import the socket.io package onto the front-end.

  2. Add the following line to script.js:

    var socket = io.connect('http://localhost:3000');
    socket.on('connect', function(data) {
    socket.emit('join', 'Hello server from client');
    });

    The socket.on() method tells the package how to handle the 'connect' event "emitted", or sent, by the server. In our case, when the socket connects to the server, it emits a message of type 'join' to the server, so that we can log the connection.

  3. Finally, add the following code to the end of server.js

    var io = require('socket.io')(httpServer);
    // other middleware from earlier goes here
    var numClients = 0;
    io.on('connection', function(client) {
    console.log('Client', numClients++, 'connected.');
    
    client.on('join', function(data) {
    console.log(data);
    });
    });

Which will set up the server side to listen for incoming socket connections, and log them once connected. The 'connection' event is built in when a new socket connects to the server, where we just add the number of connections and log it. The 'join' event is custom defined by our application so that the client can send us unique data on connection.

Test out the page again and check the console. Now we should see logs of the socket connections being made appear when a new page is connected.

Now all that's left to do is hook up the real time updates to send messages! In script.js, we can add a handler for 'chat msg' events emitted by other clients:

socket.on('chat msg', function(msg) {
    createHTMLMessage(msg, 'server');
});

And add the following code in inputElem.addEventListener(...) inside the if statement, above the inputElem.value = "" line, where we previously had a call to doPostRequest():

createHTMLMessage(inputElem.value, 'client');
socket.emit('chat', inputElem.value);

The above socket.on('chat msg', ...) call tells the socket.io how to handle 'chat msg' events emitted by the server. In our case, we just want to add them to the page as 'server' messages. Then, the socket.emit() code just tells the client to add the message locally to the front-end, then dispatch the event to the server so all other clients can receive the message. How the server does that is defined below.

In server.js, we just need to add a handler for the chat action that will broadcast to all other open sockets. This should be added right next to the client.on('join', ...) (inside the callback to io.on(‘connection’...), since it needs to be set per client on connection.

client.on("chat", function(msg) {
console.log(msg);
client.broadcast.emit('chat msg', msg);
});

Now everything should be setup, and ready to chat! Open up the page in 2 windows and test that you are able to send messages instantly between them.

Leave a Reply