How JavaScript Works: Understanding WebSockets in Nodejs with Socket.io

Lawrence Eagles
SessionStack Blog
Published in
9 min readSep 5, 2022

This is post # 72 of the series, dedicated to exploring JavaScript and its building components. In the process of identifying and describing the core elements, we also share some rules of thumb we use when building SessionStack, a JavaScript tool for developers to identify, visualize, and reproduce web app bugs through pixel-perfect session replay.

Introduction

The WebSocket API enables us to establish bi-directional communication between a client — a browser and a server. And as a result, data can flow from client to server and server to client. Also, because WebSockets are always open, they allow real-time data flow in our application.

The first step of a WebSocket is for a client to send an HTTP request to the server — asking to open a connection. And if the server agrees, it will send a 101 Switching Protocols response— at which point the handshake is complete. So the TCP/IP connection is left open, thus, allowing a bi-direction flow of data between the server and the client with very low latency.

The WebSockets API allows several clients to connect to a server simultaneously. And this connection stays open until one of the parties drops off.

A typical application of the WebSockets API is a chat application, and the image below explains how this might work:

From the image above, each client—user browser is connected via a Websocket to the chat application server. So when a user types a message and clicks send, the message gets sent down to the server via the WebSocket connection. And the server in turn sends the message up the Websockets to all the clients. Consequently, they get a notification and see the message. The point to note here is that these communications are real-time. And that means no extra user request or Ajax request is being made at any time.

The WebSockets API enables us to build real-time features by establishing a two-way connection — via a socket, between a client and a server. So WebSockets have a lot of applications in programming these include:

  • Chat application
  • Multiplayer browser games
  • Streaming applications
  • Collaborative code editing software
  • Live text for sports/news websites
  • Real-time to-do apps with multiple users.
  • Online drawing canvas applications

In this tutorial, we will learn more about WebSockets by building a chat application. And the prerequisites to gain the most from this article are outlined in the next section.

Prerequisites

To follow along in the article, the following are required:

  • Basic knowledge of Nodejs
  • The latest version of Nodejs should be installed on your machine.
  • Basic knowledge of JavaScript

Getting started

So to use the WebSockets API, we need some server code. And to get this we will build a Nodejs application.

Follow the steps below to bootstrap the Nodejs application:

  • Create an application folder and from the folder initialize a Nodejs app by running the following code on your terminal:

npm init -y

  • Install the required packages by running:

npm install express socket.io

And install dev-dependencies by running:

npm install -D nodemon

  • Configure NPM Scripts by updating the scripts property in the package.json file as seen below:
  • Now, set up the express server by creating an src folder in the root directory. And in the src folder, create an index.js file with the following code:

In the code above, we serve a static HTML file — the index.html file using the res.SendFile method. So whenever a user points the browser to http://localhost:5000/, the index.html file is rendered to the browser. And we will create this index.html file in the next section.

Also, in the code above, we set up an express server and implemented socket.IO on the server. And we will learn more about this in the next section.

But for now, start the dev-server by running npm run dev and we get:

So with our application bootstrapped, in the next section, we will focus on building the chat app properly.

Building A Chat Application With WebSockets — Socket.IO

To establish a socket connection between the browser and our Nodejs application, we will use a library called Socket.IO.

The Socket.IO library is used by installing it both on the client and the server. And it enables socket connection between the client and the server — thus, it enables real-time bidirectional event-based communication between the server and the client.

Set up Socket.IO on the server

In our current application setup, we have implemented Socket.IO on the server using the http.createrSever method from express.

When a client makes a connection with Socket.IO on the server, an event — called connection is fired. And in our current setup, Socket.IO listens for this event using the socket.on method.

And when the connection event fires, we call a callback and log made socket connection and the socket ID to the console.

This callback function takes a socket object as an argument. And this socket object refers to the instance of the socket made between the client and the server. So if ten different clients connect to the server, each client would have its socket instance.

Set up Socket.IO on the client

To set up Socket.IO on the client, create a pubic folder in the root directory. And in the public folder, create an index.html file with the following code:

And on the browser we get:

Now we need to set up Socket.IO. Add this line of code to the header section of the index.html file to load the socket.io-client:

<script src=”/socket.io/socket.io.js”></script>

The line of code above exposes an io global, the endpoint GET /socket.io/socket.io.js, and then connects.

Now to test if socket.io-client was loaded successfully, above the closing body tag, add the following code:

And refresh the browser. We get:

From the image above, we see that made socket connection followed by the socket id is logged to the console confirming that a Websocket connect has been established between the server and the client.

Also, going forward our client-side JavaScript code will be written within these script tags above the body element.

Emitting Messages With Socket.IO

In the previous sub-sections, we set up Socket.IO on the client and the server. But in this section, we will work on emitting messages via sockets.

In our chat app, when we send data — a chat message from a browser, through a socket to the server, the server receives that message and emits data — the message to all the clients that are connected to it.

So to handle this when a user clicks the send button, we will emit an event from the client to the server via the created socket.

To implement this, we need to get all the necessary DOM elements by adding the following code below the // Query DOM comment in the index.html scripts:

Next, we add an event listener to the send button to listen for click events by adding the following code below the // Emit events comment in the index.html scripts:

In the code above, we added an event listener to the send button to listen for a click event. And when a click event occurs, the socket.emit is called in the event handler callback.

The socket.emit method takes two arguments: the name of the message — in this case, chat and an object that contains the message or data we are sending to the server.

So on the server, we will add an event listener to listen for this sent event. And to do this modify the io.on method in the index.js file as seen below:

In the code above, we listen to the socket for the emission of the chat message by calling the socket.on method. And the socket.on method takes two arguments: the chat message and an event handler — callback.

Now we called io.sockets.emit method within the callback function to send this message out to all the clients connected to the server via a WebSocket. And this enables everyone in the chat room can see the message.

Note, io.sockets refers to all the WebSockets created by the different clients connected to the server. And io.sockets.emit(‘chat’, data) emits a message — the data from the client that sent the message, to all the connected clients — in the io.sockets collection.

Now with our current setup, a user can send a message from the client to our server. And the server, upon receiving the message, emits the chat message back to all sockets in the io.sockets collection. Thus, sending the message to all the connected clients.

Following this, on the client side, we need a way to display the received message on the browser. So add the following code below the // Listen for events comment in the script section in the index.html file:

In the code above, socket.on listens for a chat message and calls a callback — an event handler upon receiving the chat message. And in the event handler, we added code that renders the message to the server.

So with this, we have our basic chat functionality working. We can pass data from a client to a server and back from the server to all the clients connected via WebSocket.

Broadcasting Messages

In this section, we will use message broadcasting to notify other clients when a user is typing a message. And to implement this, add the following code below the // Broadcast feedback when user types comment:

In the code above, we add an event listener that listens for a keypress event to the message input element. And when this event fires, we emit a typing event from the event handler by calling socket.emit — passing the user name as the data.

Now we need to handle this typing event on the server and to do this modify the io.connection method in the index.js file as seen below:

In the code above, we listen to the socket for a typing event. And once that event occurs we broadcast that event by calling socket.broadcast.emit. This emits a typing event and sends the received data to all connected client except the client that send the message.

Once again we need to handle this broadcasted message on the client side. And to do this, add the following code below the // Listen for typing message comment in the index.html scripts:

From the code above, each client listens on their socket for a typing event.

Finally, update clear the feedback when the user finishes typing and clicks send. To this, modify the socket.on method below the // Listen for events comment as seen below:

Now once the typing event is fired a message is printed to show that a user a typing as seen below:

Conclusion

In this article, we learned about the WebSocket API, a technology that enables a bidirectional flow of data between a server and a client with low latency.

And we worked with the Socket.IO library, a JavaScript library that makes it easy to set up WebSockets on the client and server.

If you are interested in the source code of the chat application we built, you can clone the repository on Github here.

Lastly, I hope after this tutorial you have learned enough to use WebSockets in your application.

WebSockets in JavaScript are very helpful, as they're more efficient than polling the server for data. But to properly use the WebSocket API and get an effective result, you need to understand how to implement WebSockets using lSocket.IO API or an alternative Websocket library like WS.

So even if you feel like the proper decisions have been made, it’s always necessary to verify that this is indeed true and your users have a great experience with your product.

SessionStack utilizes pub/sub-services to process all of the ingested behavioral data from the browser in real time. As the data is being ingested, SessionStack allows you to watch user sessions as videos, allowing you to see exactly what happened during their journey.

Combining this visual information with all of the tech data from the browser such as errors, stack traces, network issues, debug data, etc. you can easily understand problematic areas in your product and efficiently resolve them.

There is a free trial if you’d like to give SessionStack a try.

SessionStack replaying a session

Interested in more about JavaScript? Check out all “How JavaScript works” publications here.

--

--