Creating A Chat Application In Node.js With Express, MongoDB, Mongoose And Socket.io

Table of Contents

  • Introduction
  • Source Code
  • Background
  • Setting up Node application
    • Creating an App using Express
    • Running our application on the browser
    • Creating Index page
  • Start developing the chat app
    • Create a model from page data
    • Setting up database
    • Creating a post-request
    • Creating a Get request for all the chat data
  • Implementing Socket.io
    • Require the package
    • Enabling the connection
    • Listen using the new HTTP server
    • Changes in script
    • Emits the event
  • Conclusion
  • Your turn. What do you think?

Introduction

In this article, we are going to create a chat application inNodeJSwith the back-end MongoDB.We will also be using Mongoose for creating the MongoDB models and Socket.io for making multi-directional chats on multiple client windows. If you are new to NodeJS, I strongly recommend you read some articles on the same here. You can also see how you can create a sample Node application with MongoDB and Mongoose here. At the end of this article, I guarantee that you will have some basic knowledge of the mentioned technologies. I hope you will like this article.

You can always see this article on my blog here.

Source Code

You can always clone or download the source code here.

Background

Creating a chat application is always an interesting this to do. It is a good way to learn a lot because you are creating some interactions with your application. And with the release of a few technologies, we can create such applications without any hassle. It is much easier than ever. Here, we are also going to create a chat application. A basic knowledge of NodeJS, MongoDB, JavaScript, and jQuery is more than enough to create this project. So, please be with me. Let’s just skip the talking and start developing.

Setting up Node application

This step requires some basic knowledge, please see some of that here. So, as mentioned in that article, we have successfully created our Package.json file and installed the required packages. Let’s review our package.json file

{
    "name": "chatapp",
    "version": "1.0.0",
    "description": "A chat application in Node JS, which uses MongoDB, Mongoose and Socket.io",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "keywords": ["Node", "JS", "MongoDB", "Mongoose", "Socket.io"],
    "author": "Sibeesh Venu",
    "license": "ISC",
    "dependencies": {}
}

Let’s install the packages now by running the below commands.

npm install --save express
npm install --save mongoose
npm install --save body-parser
npm install --save socket.io

Now, we have all the dependencies added to the package.json file

"dependencies": {
    "body-parser": "^1.18.2",
    "express": "^4.16.2",
    "mongoose": "^4.13.6",
    "socket.io": "^2.0.4"
}

Creating an App using Express

Let’s create a file named server.js and build an app using Express

var express = require("express");
var app = express();
app.listen(3020, () => {
    console.log("Well done, now I am listening...");
});

I hope you are getting the desired output; if not, please don’t worry, just double-check the codes you have written.

Running our application on the browser

Let’s run our application on port 3020 and see what we are gettinghttp://localhost:3020/.

Yes, you will get an error as cannot GET /. No worries! To fix that, you need to add the following code block to your server.js file.

app.use(express.static(__dirname));

Creating Index page

Here, I am going to create an HTML 5 page with JQuery and Bootstrap referenced in it.

<!DOCTYPE html>
<title>Creating a Chat Application in Node JS with Express, MongoDB, Mongoose and Socket.io</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.2.1.min.js" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" crossorigin="anonymous"></script>
<div class="container"><br>
    <div class="jumbotron">
        <h1 class="dispaly-4">Start Chatting</h1><br>
        <input id="txtName" class="form-control" placeholder="Name" type="text"><br>
        <textarea id="txtMessage" class="form-control" placeholder="Message"></textarea><br>
        <button id="send" class="btn btn-success">Send</button>
    </div>
    <div id="messages"></div>
</div>

As you can see, the page has two text boxes and one button. We will be creating some scripts very soon that use these controls.

Start developing the chat app

So far, it is all basic, and we have done it well. Now, it is time to go and write some advanced codes. So, are you ready?

Create a model from page data

Here, we are going to create the model from the page data, that is, from the controls we have on our page. We will be using JQuery to do so.

<script>  
    $(() => {  
        $("send").click(() => {  
            varchatMessage = {  
                name: $("#txtName").val(),  
                chat: $("#txtMessage").val()  
            }  
            postChat(chat)  
        })  
    })  
    functionpostChat(chat) {  
        console.log(chat)  
    }  
</script>  

Now, that we have got the model from the user, let’s save it to the DB.

Start chatting
Model values on the browser console

Setting up database

We are going to set up our database in mLab as mentioned in this article Using MongoDB on Node JS Application Using Mongoose. So, let’s just use Mongoose and make the needed changes.

const express = require("express");
const mongoose = require("mongoose");
const app = express();
const conString = "mongodb://admin:[email protected]:38319/mylearning";
app.use(express.static(__dirname));
const Chats = mongoose.model("Chats", {
    name: String,
    chat: String
});
mongoose.connect(conString, { useMongoClient: true }, (err) => {
    console.log("Database connection", err);
});
app.listen(3020, () => {
    console.log("Well done, now I am listening...");
});

Creating a post-request

Now, let’s create a post requesting our index.html file which will post the API in our server.js file.

Index.html

function postChat(chat) {
    $.post("http://localhost:3020/chats", chat);
}

Server.js

app.post("/chats", async (req, res) => {
    try {
        var chat = new Chats(req.body);
        await chat.save();
        res.sendStatus(200);
    } catch (error) {
        res.sendStatus(500);
        console.error(error);
    }
});

Let’s just run our application and test it out.

You may be getting an error as “(node:10824) DeprecationWarning: Mongoose:m promise(mongoose’s default promise library) is deprecated, plug in your promise library instead: http://mongoosejs.com/docs/promises.html”, here to fix this, we need to use the default promise instead of the Mongoose promise. Let’s change that. Add this code mongoose.Promise=Promiseto our server.js file. Give it a try after setting it.

Still, it is not working right, you are getting undefined date the place,varchat=newChats(req.body)in our Post API. At this stage, we will have to use our body-parser packages, do you remember the package we have installed? Let’s just require that packagevarbodyParser=require("body-parser")add the preceding codes to our server.js file.

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

Now, this will convert the request to a JSON object by default. Give it a try again, I am sure you will get the actual value instead of undefined.

Creating a Get request for all the chat data

We have written codes to write our data into our database. We will have to show this data on our page, right? Here, we are going to write the get requests in our index.html page which will call the get API.

Index.html

function getChats() {
    $.get("/chats", (chats) => {
        forEach(addChat)
    })
}
function addChat(chatObj) {
    $("#messages").append(`<h5>${name}</h5><p>${chatObj.chat}</p>`);
}

And call the function getChats() in the document-ready event.

Server.js

app.get("/chats", (req, res) => {
    Chats.find({}, (error, chats) => {
        res.send(chats)
    })
})

Here, we are passing {} to our find function, this means, we are going to get all the chats without any filter. Just run your application now, and check whether you are getting the chat messages you sent.

Start chatting
Retrieving data from a MongoDB

Implementing Socket.io

Now, the chat we are sending is getting saved to our database and we can load the same on page load. Is it the behavior of a perfect chat application? No, a perfect chat application will be able to,

  1. Show the chat message to the UI right after the data gets inserted into the database
  2. Show the chats in multiple clients, here in our application, if you are opening the URL in multiple browser instances, and if you need to show the chats to both instances, you will have to refresh the pages right? This is not a recommended way

That’s why we are going to implement Socket.io in our application.

Require the package

Unlike the other packages, adding socket.io to the application is a different process, we will have to require the HTTP server first, and then, set up our app. You can see more information on the socket.io here.

var http = require("http").Server(app)
var io = require("socket.io")(http)

Enabling the connection

To enable the connection, we need to use the function io.on.

io.on("connection", (socket) => {
    console.log("Socket is connected...")
})

Listen using the new HTTP server

Now, that we have a new HTTP server, we should change our listen code to our new HTTP.

varserver = http.listen(3020, () => {  
    console.log("Well done, now I am listening on ", server.address().port)  
})  

Changes in script

Let’s listen to the event “chat” now in our HTML page.

var socket = io()
socket.on("chat", addChat)

Please do not forget to include the socket.io.js reference in our index page, otherwise, you may get an error as “Uncaught ReferenceError: io is not defined”

Emits the event

Once the above step is completed we need to make sure we are emitting the new event on our Post API.

app.post("/chats", async (req, res) => {
    try {
        var chat = new Chats(req.body)
        await chat.save()
        res.sendStatus(200)
        // Emit the event
        io.emit("chat", req.body)
    } catch (error) {
        res.sendStatus(500)
        console.error(error)
    }
})

Let’s just run our application in two browser instances and check for the output.

Two browser output
Socket.io Output

Please make sure that you are getting the chats in the second instance when you send it from the first instance of the browser and vice versa.

Conclusion

Thanks a lot for reading. Did I miss anything that you may think is needed? Did you find this post useful? I hope you liked this article. Please share your valuable suggestions and feedback.

Your turn. What do you think?

A blog isn’t a blog without comments, but do try to stay on topic. If you have a question unrelated to this post, you’re better off posting it on C# Corner, Code Project, Stack Overflow, or Asp.Net Forum instead of commenting here. Tweet or email me a link to your question there and I’ll try to help if I can.


Similar Articles