The MEAN Stack - Node.js

So far in the MEAN series, you have learnt about setting up your environment for MEAN stack, MongoDB and Express basics. Let’s talk about how you can work with Express and Node together. Express and Node dance very well together with JavaScript playing the orchestra!

Node.js is built on Chrome’s V8 JavaScript engine and it enables you to run JavaScript on the server side. Yes, JavaScript... on the server side!!! But why would you do that? It so happens that Node takes the goodness of JavaScript right to the server so that you have an event-driven and non-blocking I/O model.

Pop Quiz: Will you have a deadlock if there is no lock? Answer: No, never! (what kind of question was that, anyways?!?)

Node.js is Asynchronous

In Node, the function calls are asynchronous by default. This paradigm is different from ASP.NET or PHP applications where things are synchronous by default. Also, there are no locks in Node, and hence you can’t deadlock the process! It doesn’t mean that you can’t write bad apps, but if you become a seasoned Node developer, you would be dealing with asynchronous code as your second nature.

Node.js is single threaded

Compared to other programming frameworks like ASP.NET & Apache, where there are multiple threads handling requests, Node chooses to use an event loop. Due to this fact, it is able to scale really well where the I/O volume is high.

Node.js is an environment

You have to do everything yourself. However, there is plenty of support in the form of npm (node package manager). Understanding node is more about understanding the ecosystem along with the core technicality so that you don’t reinvent the wheel.

Node.js is modular

Node is a module based system. You are supposed to require the dependencies, and things just work.

  • Create a folder for your Node application (I’ll call it nodedemo)
  • Inside the folder create a file called mylibrary.js and paste the code below:
function AddNumbers(a, b)
{
	console.log("%s + %s = %s", a, b, a+b);
}

function DoSomethingSlow()
{
	setTimeout(function(){console.log("Sorry, I am a slow function...")}, 3000);
}

exports.DoSomethingSlow = DoSomethingSlow;
exports.AddNumbers = AddNumbers;
  • Create another file called server.js and paste the code below:
var mylib = require('./mylibrary');
mylib.DoSomethingSlow();
mylib.AddNumbers(10,15);
  • There are multiple things going on here:
    • In the library file, you can see module exports at the bottom. This is how portions of your library is exposed to the outside world. You can create a library as big as you like, and use exports as needed.
    • DoSomethingSlow is a function that says, write to the console after 3 seconds.
    • In server.js file, note that the first line is a require which loads the dependent library and initialises the mylib object so that you can make the exported calls. To execute the script, use the following command:
node server.js
  • In a typical synchronous application, you would have found that the call DoSomethingSlow would have blocked the output and you would have seen the result of AddNumbers after 3 seconds. Not with Node. Here you will find the output will get printed straight away, and after 3 seconds you will get the result from DoSomethingNew
10 + 15 = 25
Sorry, I am a slow function...

npm is massive!

  • It is the largest package ecosystem, ever! Read more about it here. The benefit you get from npm is not immediately apparent, but the more you work in JavaScript, the more you will realize the benefits of code reuse.

Setting up a Node web server

This one is really easy. require loads the dependency you need and if you take a look at the code below, you will find a typical Node function. You can modify your server.js file to contain the code like so:

var http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello, World!\n');
}).listen(8080, "127.0.0.1");

console.log('Server running at http://127.0.0.1:8080/');

Execute node server.js, and browse to http://localhost:8080. You should be greeted with Hello world!

###Wiring Express and Mongo with Node Notice that you can create your webserver in Node directly after requiring http. But you wouldn’t really want to handle all that logic yourself, right? This is where Express helps you. You can leave the request and route handling job to Express as a middleware and do the heavy lifting using Node. That way you get the best of both worlds. In the next section, you will learn how to use mongodb library to connect to the mongod service and get you the data that you need.

  • Create a new folder (I am calling it meandemo).
  • Create a new file called package.json and paste the following:
{
  "main": "server.js",
  "dependencies": {
    "consolidate": "^0.13.1",
    "express": "^3.21.2",
    "mongodb": "^1.4.39",
    "swig": "^1.4.2"
  }
}
  • Open terminal and type npm install. This will install all dependencies.
  • Start mongod
  • Start mongo shell mongo and type the following commands one by one:
use mongohello
db.info.insert({"name":"Attosol","country":"India"})
  • You have basically created a new mongohello collection and inserted a document in info collection.
  • Create a folder called views and in this folder create a file called hello.html.
  • Add the following text in the hello.html file.
<h1>Hello from {{name}}, {{country}}</h1>
  • Notice that name and country keys are exactly same as what was inserted in the collection.
  • Now that we have data in the database, and view to render the data, let’s create a page which will do the rendering for us.
  • Create a file called server.js and paste the code below:
var express = require('express'), 
	app = express(),
	cons = require('consolidate'),
	MongoClient = require('mongodb').MongoClient;
	Server=require('mongodb').Server;

app.engine('html', cons.swig);
app.set('view engine', 'html');
app.set('views', __dirname + "/views");

var mongoclient = new MongoClient(new Server('localhost', 27017, { 'native_parser' : true }));

var db = mongoclient.db('mongohello');

app.get('/', function(req, res){
	db.collection('info').findOne({}, function(err, doc){
		res.render('hello', doc );
	});
});

app.get('*', function(req, res){
	res.send("Page not found", 404);
});

mongoclient.open(function(err, mongoclient){
    if (!err){
        app.listen(8800);
        console.log("Listening on 8800");
    }
});
  • You can see that an express application is initialised and the template engine is set to cons.swig. Later on, this approach will be changed since Angular will be used to complete the A component of MEAN. For now, let’s simply settle with swig. The view files are located in views folder (hello.html). In the code above, var mongoclient initialises the variable but doesn’t open the connection. Notice that, app.get is mapped for the default route (/) and it tells the server to render hello.html file the doc output. doc output is nothing but the result of findOne for info collection. Eventually, the mongoclient opens the database connection, and if it happens successfully, it starts listening on port 8800.
  • Start your server using node server.js
  • If you have followed the instructions correctly, you should be able to see the following:

Hello from Attosol, India

  • At this point you have a working node server that is using express and able to talk to the mongo database!

Enjoy the stack 👍

© 2023, Attosol Private Ltd. All Rights Reserved.