Real-Time Web with JavaScript — III

Ayoub NEJJARI
The TechCave
Published in
6 min readJun 17, 2017

--

Alright. So, we’ve seen how communication over the web evolved and why we needed something robust to have real-time experience. In the second post, we took a closer look at websockets and how they are implemented on clients as well as servers. And I saved the best for the last.

We’re going to look at a real worl example using Node and SocketIo. Before we do that though, I need to stress some important points:

  • WebSockets were designed to work well with firewalls and proxies. However, due to security concerns, some proxies change the upgrade headers and cause the connection to break. Others will time out after a while, etc. To avoid these issues, it’s better to use the wss instead of ws for encrypted connections. Also, always have a backup plan in case you’re dealing with old browsers that do not support websockets.
  • Real-Time applications’ architecture is event-driven. And With Node’s non-blocking I/O, event-driven nature, implementing websockets and building real-time apps with it is the perfect way to go.
  • A Real-time app doesn’t necessarily have to be entirely real-time. In fact, it’s common to implement real-time just for certain models.

Alright, Let’s get started!

https://www.tumblr.com/search/let's%20get%20down%20to%20business%20gif

So, we are going to be building a chat room using Node, Express, and SocketIO. I will include and explain just the important parts of the app. And somewhere below, you’ll find a link to the source code of the app.

If you want to code along, you should have node installed. Then

 npm install --save socket.io express

let’s create our Server:

Let’s explain briefly what happened here.

First, we required the modules we need, we set the PORT, and created an express app. After that, we created an HTTP server that will serve our app. So far so good. The next line is where all the fun starts. We created an instance of the socket.io module and bound it to the HTTP server.

So when using express, here are the first steps:

  • 1: Create an express app;
  • 2: Create an http server that will serve the app;
  • 3: Bind the server with a new socket.io instance;

There is a second way for creating a socket.io instance:

const Server = require('socket.io');
let io = new Server(httpServer);

Lastly, we set our app to listen on PORT.

Now before we go to the front-end, let’s add a new line below the server binding line telling the server to listen for clients that connects via websockets:

io.sockets.on('connection', (socket) => {
// all communications will happen here
}

What we are saying here is that, on every socket connection…, and we are passing the socket, which represent the client. Make sense? No? Follow along and everything will make sense eventually.

Connecting the frontEnd

On the frontend, it’s much easier.

First we should have the socket.io library in the client as well. That will expose to our app the io namespace that we’ll use to connect to our server and communicate with it.

let socket = io.connect();
// on connection
socket.on('connect', () => {
console.log('connected!');
});

Alright, take a deep breath. Nothing fancy here actually. We just created a socket and connected to the server by calling .connect(). This method takes a url as anrgument. But if we don’t explicitly specify any, it will connect to the server that is actually serving the app. Then, we create our first handler. It basically says, upon the connection, which is what happened in the first line, log the string “connected!” to the console.

This will happen every time a new user connects to the server.

Since most events will be coming from the client side, let’s write the first one. Let’s imagine we have a form to create a user and enter a chat room.

On form submission we would say this:

socket.emit('createUser', userInput.val(), function(data) {
if (data) {
$(loginBox).hide();
$(chatBox).show();
}
});

emit is used on sockets to, well, emit a message. With socketIO you can create and emit any event you want, with any data. JSON objects and binary data are supported. And in case you sent a JSON object, you don’t have to stringify it and parse it. socketIO does that for you.

So, here we are emitting a ‘createUser’ event, providing the data as the second argument, and passing a callback. This callback will execute after the sever receives the data and confirms it. We’ll see how in a sec. After that, we are just using jQuery to hide the login input and showing the messaging box.

Now, let’s go back to the server and see what is going on:

Handling and Emitting events on the Server

using .on() whether on the server or the client allows us to listen for messages and act upon them. so here we are listening for the ‘createUser’ event we emitted on the client. The second argument is a callback that takes the data coming from the client, which is the username (userInput.val()), and the callback that will be executed on the client. Then, we attached the username to the socket, we will need that to attach messages with their senders. After that we push the logged in user into the connectedUsers.

Finally, we emit the “users” event to all connected sockets.

Phew! This sounds like a long story and a whole lot of work!

Actually, that’s not true. All this happens fast, real time, and in an efficient way. You don’t believe me? Here is the app, which I will hand in its source code later, live and working. Send the link to your friend, or use two browser windows and enjoy the old way chat! It reminds me of MSN.

P.S. You may want to wait few seconds for the app to awake, Heroku puts them in sleep mode after a period of inactivity.

Let’s proceed

I’m not going to include everything here, I’ll leave that to you to explore.

Let’s see what will happen on the client when the ‘users’ message is sent, which sends the connectedUsers array.

When the client receives the ‘users’ it will update the users list on the view. That will happen every time a new user log in or disconnect. The ‘disconnected’ event is the message sent by the server when a user disconnects. It happens when a user closes the browser window or the tab.

Here is the code on the server:

socket.on('disconnect', () => {
if(!socket.user) return;
connectedUsers.splice(connectedUsers.indexOf(socket.user), 1);
io.sockets.emit('disconnected', connectedUsers);
});

There is no ‘disconnect’ message emitted from the client, this is defined by socketIO, which is an event emitted upon , as we said, closing the browser or the tab.

After a user disconnects, we want to inform all the other users, aka other sockets. So we first remove the disconnected user from the connectedUsers. Then we send the new array to the client on the ‘disconnected’ message.

Well, I think that’s what the docs and other resources are for, to clarify and explain what seems to be too much, and to teach you what’s enough and more. Right?

Aye Mate!

I hope you enjoyed the last post, if you missed the first two, check them out!

Oh! I almost forgot! As I promised here is the github repo of the app! Enjoy!

I hope you enjoyed this post. If you enjoyed it, please hit the ❤ below , that’s my heart so don’t hit too hard, and share it. Thanks! ^^

--

--