Examples on MVR ,blocking and non-blocking nature of Node



We will be looking at the following in this post:




1) MVR design pattern with Node

a)     In this example we will illustrate the MVR pattern. Let us go to the cmd prompt and traverse to a new project(create a folder say under c:\demo3)
b)     In the cmd prompt under demo3, create the following files
a.      app.js
b.     router.js
c.      requestHandler.js
d.     server.js
                                                  
c)     app.js is our controller. In this file we define our mappings between incoming request url and the respective route request handlers.

The code in app.js is as follows:

var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handleRoutes = {}
handleRoutes["/"] = requestHandlers.landing;

d)     The server.js which is included in the app.js is responsible for creating a server instance for rendering the web page.
The code in server.js is as follows:

var http = require("http");
var url = require("url");


function init(route, handle) {

         function onRequest(request, response) {
           var pathname = url.parse(request.url).pathname;
           var content = route(handle,pathname);
           response.writeHead(200, {"Content-Type": "text/plain"});
           response.write(content);
           response.end();
         }
      
         http.createServer(onRequest).listen(3001);
         console.log("Server has started..........");

}

exports.init = init;

e)     The point to note from the server.js is the init function created as a wrapper to the http server creation. “exports.init” exports this function to be consumed from the app.js.

f)      The other learning from the server.js is passing the method “onRequest “ instead of an anonymous function. Please refer my post here to see the other style to create the server instance with anonymous function.
g)     The router.js is responsible for the routing. This is invoked from the server.js.

function route(handle,pathName) {
  console.log("Routing the request.......... " + pathName);
  if (typeof handle[pathName] === 'function') {
    return handle[pathName]();
  } else {
    console.log("No request handler found." + pathname);
    return "404";
  }
}

exports.route = route;

h)    The request handler defines all the handlers for the incoming requested URL. In our app.js we have defined a mapping between incoming request “/” will be handled by a function “landing” in this file.

The code in requestHandler.js is as follows:


function landing() {
  console.log("Request handler landing was called.");
  return "Hello landing ..............................................";
}

i)       Now at the root of the demo3 project in cmd prompt, hit “node app.js”
j)       Run the browser and hit : localhost:3001

You should see the output as follows:


Congratulations you have your app running with MVR pattern.


2) Application to illustrate blocking and non-blocking nature of node

We will expand the above example to learn the advantages of event driven model with a practical example.

In most of our applications we see that we may have heavy duty functionality such as importing a massive file or doing a heavy duty advanced search or waiting for a database task to be done to proceed forward. This creates a blocking nature on the incoming request leading to very poor user experience. Certain frameworks like Adobe Flex do have the event driven model available for use just as node.js.

Blocking Nature:

 



The controller is blocked from proceeding to do concurrent activity in such cases leading to slow user responses.

Add the following code to previous example to see the same:


a)     In the app.js add another mapping for a new route and the respective handler

handleRoutes["/blocking"] = requestHandlers.blocking;

b)     In the requestHandlers.js add the following lines of code to define the handler:
   

function blocking() {
    sleep(10000);
  return "Blocking now.............";
}

function sleep(milliSeconds) {
    var startTime = new Date().getTime();
    while (new Date().getTime() < startTime + milliSeconds);
  }


c)     Restart the server by doing CTR+C and again node app.js on the cmd prompt.
Aliter: Install the nodemon by hitting npm install nodemon, a monitoring tool. Running an application as “nodemon app.js” in place of “node app.js” on the cmd prompt does not need a restart of the server while developing applications.


d)     Hit the url on the browser as localhost:3001/blocking
e)     You will see the output on the browser after 10 seconds.
f)      Now this does not completely show you the blocking nature does it? So follow the following steps carefully to see what my end goal is on blocking:
g)     Open two browser instances (do not use two tabs on same browser)
h)    On the first browser instance hit the URL: localhost:3001/blocking
i)       Quickly On the second browser instance hit the URL: localhost:3001/
j)       What you will observe is the actual blocking nature where the second request reaches the user after 10 seconds due to the blocking nature from the first request.

Amazing isn’t it?? Now time to see the problem fixed by an event driven model from node.

Non-blocking Nature:

Let us see how this is solved by means of a child process in node.

a)     Install the child process by hitting “npm install child_process” on the cmd prompt.
b)     In the app.js add another mapping for a new route and the respective handler

handleRoutes["/nonBlocking"] = requestHandlers.nonBlocking;

c)     In the requestHandlers.js add the following lines of code to define the handler:

function nonBlocking(){
  var content = "hi how are u.............";
  exec("find/", function (error, stdout, stderr) {
   console.log("request processing started now.............................");
   sleep(10000);
   console.log("request processing ended now.............................");
  });
  return "processing...........";
}


d)     I want you to now keep the browser in a smaller window besides the command prompt such that you can parallel see the server side console.log and the UI behaviour to see the non-blocking nature of node.
e)     Hit localhost:3001/nonBlocking on the browser

Observe the following:

1)     Instantaneously output is received in the browser without any delay.
2)     On the cmd prompt you will see that the child process has started and ends after 10 seconds.

More details on child_process can be found here:






4 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. The code sample given here does not work after creating all the files needed.

    ReplyDelete