21
NovA Guide to Build Real-Time Application Using Node.js
Web development is going through unprecedented developments all through the beginning of the 21st century. While a lot of emphases have been laid down to enhance the interface and interactive features, it all comes down to saving time and making the applications and utilities fast. And this has become a benchmark for the developers these days.
A Guide to Build Real-Time Application Using Node.js:-
We are all familiar with messaging applications such as Whatsapp, Facebook messenger, and so on. These are some of the real-time applications that we use daily. However, there are several other purposes that real-time application development serves. Be it the payment apps,delivery apps, online gaming applications, and a lot more.
While there are several languages that developers rely on to develop real-time applications such as Java, Kotlin, Angularjs, and several more, we will focus on Node.js as the programming language. Node.js is an open-source language and its event-driven and asynchronous nature makes it one of the best languages to program a real-time application. Here we will demonstrate the use of Node.js language to develop real-time applications through developing a chatting application. The concepts that will be utilized in developing the application can be used to develop other applications as well, even though they are specific for this demonstration.
Read More - Node JS Interview Questions for Freshers
Building a Real-Time Application
As we already discussed, real-time applications come quite useful in cases when we don’t want the client to refresh the pages now and then to retrieve new information. For this purpose, developers need to make use of a communication protocol called the WebSocket. It allows both the client and the server to initiate communication. Here, the server can send data at any time without the client having to make requests for it (refresh the pages for example).
We can use the WebSocket API to communicate using WebSockets while building an application. However, while programming in Node.js, we can make use of the Socket.io API from the library which provides a much simpler implementation of WebSockets API to use. Now that we have discussed some basic prerequisites of developing a real-time application, let's proceed further to develop a real-time chat application. The application will consist of a simple chat-room where any number of users will be able to connect, and a message sent by a user will be visible to all the users across the platform.
The following set of features will be included further- a user being able to change its user name, being able to send messages to the chatroom, and being able to see whether another user is typing a message in real-time. Now that we have defined our requirements regarding the application, let us start building the application.
You should know things about node.js developmentbefore coding. Firstly, we need to set up the Application Environment. Set up a new directory for the application; run the npm init to set up the package.json file, and assign app.js as the main script.We will make use of the express, ejs, and nodemon packages to build the application apart from socket.io. The ejs is a JavaScript template engine. Nodemon is used for the ease of development, it allows for the incorporation of changes to the application consequently as the codes are altered without the need to restart the application every time a change to the code is made. Following command installs the express, ejs, and socket.io
npm install express ejs socket.io --save
Following command installs nodemon
npm install nodemon --save-dev
Add the following script to the package.json file to start the program with nodemon-
"scripts": { "start": "nodemon app.js", },
Start the application using the following command in the command line-
npm run start
The next step is to develop an Application structure. For this, it is needed to construct a few directories and a file app.js. After this process the application structure will look as follows-
|--app.js |--views |--node_modules |--package.json |--public |--css |--js
- app.js: file is used to host server-side code
- views: folder containing the views (ejs)
- node_modules: where dependencies are installed
- package.json: npm configuration file
- public: is the directory. It is used to store assets such as css files, javascript files (for the client-side), and images
Now, open the file app.js and paste the following code to get the express running-
const express = require('express') const socketio = require('socket.io') const app = express() app.set('view engine', 'ejs') app.use(express.static('public')) app.get('/', (req, res)=> { res.render('index') }) const server = app.listen(process.env.PORT || 3000, () => { console.log("server is running") })
When an express is designed and using ejs as template framework, sockets.io initialization can be started. For this it is needed to include the below coding format to finish app.js document.
Next, we need to initialize socket.io from the express. After the initialization, we need to set up an event using io.on() which will be triggered by every new connection to the socket.
In order to design the Front-end, we will see how the connection to the server works, and how to emit and capture socket events.
Create an index.ejs and paste the following code to create a template into the views folder-
<!DOCTYPE html> <head> <title>Simple realtime chatroom</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"> </head> <body> <div class="container"> <div class="title"> <h3>Realtime Chat Room</h3> </div> <div class="card"> <div class="card-header">Anonymous</div> <div class="card-body"> <div class="input-group"> <input type="text" class="form-control" id="username" placeholder="Change your username" > <div class="input-group-append"> <button class="btn btn-warning" type="button" id="usernameBtn">Change</button> </div> </div> </div> <div class="message-box"> <ul class="list-group list-group-flush" id="message-list"></ul> <div class="info"></div> </div> <div class="card-footer"> <div class="input-group"> <input type="text" class="form-control" id="message" placeholder="Send new message" > <div class="input-group-append"> <button class="btn btn-success" type="button" id="messageBtn">Send</button> </div> </div> </div> </div> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script> <script src="/js/chatroom.js"></script> </body> </html>
messageBtn is the button that we will use to send a message, and usernameBtn is the ID for the button that we will use to submit a new username. The inputs will have the IDs username and message respectively. The ID message-list will contain all the user messages, and in case a user is typing a message, the information will appear inside the div with class info.
"http://localhost:3000/
in the browser will show how that app would look like-The next process is to connect the Front-end to the server to make the interface work. For this, inside the js folder of the public library, and inside the JavaScript file, we need to connect to the socket from the Front-end through executing the following code-
(function connect(){ let socket = io.connect('http://localhost:3000') })()
The website on the terminal will now show the following-
This means that the app is working and now we need to develop the desired functions.
Changing the User-Name
The default username for every new user will be ‘Anonymous’. Let us develop the back-end for changing the user-name when the event change_username is triggered by the Front-end. On the app.js file, add the following code to the connection event-
io.on('connection', socket => { console.log("New user connected") socket.username = "Anonymous" socket.on('change_username', data => { socket.username = data.username }) })
Now we need to make adjustments to the Front-end so that clicking the button emits an event to the server with the name change_username. We will do this by adding an event listener to usernameBtn inside chatroom.js.
(function connect(){ let socket = io.connect('http://localhost:3000') let username = document.querySelector('#username') let usernameBtn = document.querySelector('#usernameBtn') let curUsername = document.querySelector('.card-header') usernameBtn.addEventListener('click', e => { console.log(username.value) socket.emit('change_username', {username: username.value}) curUsername.textContent = username.value username.value = '' }) })()
Now when a new Username is submitted and the page is reloaded, the username will be changed to the new one.
Sending Messages
The next feature to develop is that of sending messages. In this case, the Front-end will emit a new_message event, which then will need to be sent to all the connected clients, so that they can print the new message. As we did before, we will need to configure the Front-end to emit a new_message event when a new message is submitted. Because the client-side needs to be configured as well, the application will also have to respond to the receive_message events on the Front-end and show the message on the web page. To accomplish these functions, enter the following code in the connect function in the chatroom.js.
let message = document.querySelector('#message') let messageBtn = document.querySelector('#messageBtn') let messageList = document.querySelector('#message-list') messageBtn.addEventListener('click', e => { console.log(message.value) socket.emit('new_message', {message: message.value}) message.value = '' }) socket.on('receive_message', data => { console.log(data) let listItem = document.createElement('li') listItem.textContent = data.username + ': ' + data.message listItem.classList.add('list-group-item') messageList.appendChild(listItem) })
During the events, we change our DOM to deliver the message on the screen. For the new_message event that we receive in the back-end, a new event needs to be emitted to all the users. We will use io.sockets.emit()function for that purpose. Enter the following code in the connect function in the app.js file-
io.on('connection', socket => { console.log("New user connected") socket.username = "Anonymous" socket.on('change_username', data => { socket.username = data.username }) //handle the new message event socket.on('new_message', data => { console.log("new message") io.sockets.emit('receive_message', {message: data.message, username: socket.username}) }) })
The feature to send messages is now ready and we can head to develop the third feature.
Typing Display
This feature will add a real-time look to the designed application. For this, whenever a keyboard button is pressed, we need the message input box to emit a typing event.This event will tell the server that a user is typing a message. The client-side listens to the typing events as well to know if a user is currently typing. To accomplish this, inside the connect function in the chatroom.js, add the following code-
let info = document.querySelector('.info') message.addEventListener('keypress', e => { socket.emit('typing') }) socket.on('typing', data => { info.textContent = data.username + " is typing..." setTimeout(() => {info.textContent=''}, 5000) })
In case a user is typing a message, the message room will show the text ‘typing’ for 5 seconds. To configure the back-end to handle the above events, we use the following code-
socket.on('typing', data => { socket.broadcast.emit('typing', {username: socket.username}) })
Socket.io uses the function to notify the users that a user is typing a message. All the users except the user typing the message gets notified about the message.
Conclusion
So, we have developed our test chat-room which involved three real-time features that best demonstrate the process which needs to be undertaken to develop a real-time application through Node.js. It is just a basic program and therefore a lot of other features and creative ideas can be implemented to make other interesting real-time applications.Take our Nodejs skill challenge to evaluate yourself!
In less than 5 minutes, with our skill challenge, you can identify your knowledge gaps and strengths in a given skill.