Go Top
advertise here!!!

Library || READ MORE || DOWNLOAD PDF || QUESTION ANSWERS || HOME

  • ABOUT NODE.JS ↓

    About Node.js

    The aim of this document is to get you started with developing applications with Node.js, teaching you everything you need to know about "advanced" JavaScript along the way. It goes way beyond your typical "Hello World" tutorial.

    Status

    You are reading the final version of this book, i.e., updates are only done to correct errors or to reflect changes in new versions of Node.js. It was last updated on March 24, 2015.

    The code samples in this book are tested to work with Node.js version 0.12.0.

    Intended audience

    This document will probably fit best for readers that have a background similar to my own: experienced with at least one object-oriented language like Ruby, Python, PHP or Java, only little experience with JavaScript, and completely new to Node.js.

    Aiming at developers that already have experience with other programming languages means that this document won't cover really basic stuff like data types, variables, control structures and the likes. You already need to know about these to understand this document.

    However, because functions and objects in JavaScript are different from their counterparts in most other languages, these will be explained in more detail.

    Structure of this document

    Upon finishing this document, you will have created a complete web application which allows the users of this application to view web pages and upload files.

    Which, of course, is not exactly world-changing, but we will go some extra miles and not only create the code that is "just enough" to make these use cases possible, but create a simple, yet complete framework to cleanly separate the different aspects of our application. You will see what I mean in a minute.

    We will start with looking at how JavaScript development in Node.js is different from JavaScript development in a browser.

    Next, we will stay with the good old tradition of writing a "Hello World" application, which is a most basic Node.js application that "does" something.

    Then, we will discuss what kind of "real" application we want to build, dissect the different parts which need to be implemented to assemble this application, and start working on each of these parts step-by-step.

    As promised, along the way we will learn about some of the more advanced concepts of JavaScript, how to make use of them, and look at why it makes sense to use these concepts instead of those we know from other programming languages.

  • JS & NODE.JS ↓

    JavaScript and Node.js

    JavaScript and You

    Before we talk about all the technical stuff, let's take a moment and talk about you and your relationship with JavaScript. This chapter is here to allow you to estimate if reading this document any further makes sense for you.

    If you are like me, you started with HTML "development" long ago, by writing HTML documents. You came across this funny thing called JavaScript, but you only used it in a very basic way, adding interactivity to your web pages every now and then.

    What you really wanted was "the real thing", you wanted to know how to build complex web sites - you learned a programming language like PHP, Ruby, Java, and started writing "backend" code.

    Nevertheless, you kept an eye on JavaScript, you saw that with the introduction of jQuery, Prototype and the likes, things got more advanced in JavaScript land, and that this language really was about more than window.open().

    However, this was all still frontend stuff, and although it was nice to have jQuery at your disposal whenever you felt like spicing up a web page, at the end of the day you were, at best, a JavaScript user, but not a JavaScript developer.

    And then came Node.js. JavaScript on the server, how cool is that?

    You decided that it's about time to check out the old, new JavaScript. But wait, writing Node.js applications is one thing; understanding why they need to be written the way they are written means - understanding JavaScript. And this time for real.

    Here is the problem: Because JavaScript really lives two, maybe even three lives (the funny little DHTML helper from the mid-90's, the more serious frontend stuff like jQuery and the likes, and now server-side), it's not that easy to find information that helps you to learn JavaScript the "right" way, in order to write Node.js applications in a fashion that makes you feel you are not just using JavaScript, you are actually developing it.

    Because that's the catch: you already are an experienced developer, you don't want to learn a new technique by just hacking around and mis-using it; you want to be sure that you are approaching it from the right angle.

    There is, of course, excellent documentation out there. But documentation alone sometimes isn't enough. What is needed is guidance.

    My goal is to provide a guide for you

    A word of warning

    There are some really excellent JavaScript people out there. I'm not one of them.

    I'm really just the guy I talked about in the previous paragraph. I know a thing or two about developing backend web applications, but I'm still new to "real" JavaScript and still new to Node.js. I learned some of the more advanced aspects of JavaScript just recently. I'm not experienced.

    Which is why this is no "from novice to expert" book. It's more like "from novice to advanced novice".

    If I don't fail, then this will be the kind of document I wish I had when starting with Node.js.

    Server-side JavaScript

    The first incarnations of JavaScript lived in browsers. But this is just the context. It defines what you can do with the language, but it doesn't say much about what the language itself can do. JavaScript is a "complete" language: you can use it in many contexts and achieve everything with it you can achieve with any other "complete" language.

    Node.js really is just another context: it allows you to run JavaScript code in the backend, outside a browser.

    In order to execute the JavaScript you intend to run in the backend, it needs to be interpreted and, well, executed. This is what Node.js does, by making use of Google's V8 VM, the same runtime environment for JavaScript that Google Chrome uses.

    Plus, Node.js ships with a lot of useful modules, so you don't have to write everything from scratch, like for example something that outputs a string on the console.

    Thus, Node.js is really two things: a runtime environment and a library.

    In order to make use of these, you need to install Node.js. Instead of repeating the process here, I kindly ask you to visit the official installation instructions. Please come back once you are up and running.

    Hello World

    Ok, let's just jump in the cold water and write our first Node.js application: "Hello World".

    Open your favorite editor and create a file called helloworld.js. We want it to write "Hello World" to STDOUT, and here is the code needed to do that:

    console.log("Hello World");

    Save the file, and execute it through Node.js:

    node helloworld.js

    This should output Hello World on your terminal.

    Ok, this stuff is boring, right? Let's write some real stuff.

  • A BLOWN WEB APPLICATION WITH NODE.JS ↓

    A full blown web application with Node.js

    The use cases

    Let's keep it simple, but realistic:

    • The user should be able to use our application with a web browser
    • The user should see a welcome page when requesting http://domain/start which displays a file upload form
    • By choosing an image file to upload and submitting the form, this image should then be uploaded to http://domain/upload, where it is displayed once the upload is finished

    Fair enough. Now, you could achieve this goal by googling and hacking together something. But that's not what we want to do here.

    Furthermore, we don't want to write only the most basic code to achieve the goal, however elegant and correct this code might be. We will intentionally add more abstraction than necessary in order to get a feeling for building more complex Node.js applications.

    The application stack

    Let's dissect our application. Which parts need to be implemented in order to fulfill the use cases?

    • We want to serve web pages, therefore we need an HTTP server
    • Our server will need to answer differently to requests, depending on which URL the request was asking for, thus we need some kind of router in order to map requests to request handlers
    • To fulfill the requests that arrived at the server and have been routed using the router, we need actual request handlers
    • The router probably should also treat any incoming POST data and give it to the request handlers in a convenient form, thus we need request data handling
    • We not only want to handle requests for URLs, we also want to display content when these URLs are requested, which means we need some kind of view logic the request handlers can use in order to send content to the user's browser
    • Last but not least, the user will be able to upload images, so we are going to need some kind of upload handling which takes care of the details

    Let's think a moment about how we would build this stack with PHP. It's not exactly a secret that the typical setup would be an Apache HTTP server with mod_php5 installed. Which in turn means that the whole "we need to be able to serve web pages and receive HTTP requests" stuff doesn't happen within PHP itself.

    Well, with node, things are a bit different. Because with Node.js, we not only implement our application, we also implement the whole HTTP server. In fact, our web application and its web server are basically the same.

    This might sound like a lot of work, but we will see in a moment that with Node.js, it's not.

    Let's just start at the beginning and implement the first part of our stack, the HTTP server.

  • BUILD THE APPLICATION STACK ↓

    Building the application stack

    A basic HTTP server

    When I arrived at the point where I wanted to start with my first "real" Node.js application, I wondered not only how to actually code it, but also how to organize my code. Do I need to have everything in one file? Most tutorials on the web that teach you how to write a basic HTTP server in Node.js have all the logic in one place. What if I want to make sure that my code stays readable the more stuff I implement?

    Turns out, it's relatively easy to keep the different concerns of your code separated, by putting them in modules.

    This allows you to have a clean main file, which you execute with Node.js, and clean modules that can be used by the main file and among each other.

    So, let's create a main file which we use to start our application, and a module file where our HTTP server code lives.

    My impression is that it's more or less a standard to name your main file index.js. It makes sense to put our server module into a file named server.js.

    Let's start with the server module. Create the file server.js in the root directory of your project, and fill it with the following code:

    var http = require("http");
    
    http.createServer(function(request, response) {
      response.writeHead(200, {"Content-Type": "text/plain"});
      response.write("Hello World");
      response.end();
    }).listen(8888);
    

    That's it! You just wrote a working HTTP server. Let's prove it by running and testing it. First, execute your script with Node.js:

    node server.js

    Now, open your browser and point it at http://localhost:8888/. This should display a web page that says "Hello World".

    That's quite interesting, isn't it. How about talking about what's going on here and leaving the question of how to organize our project for later? I promise we'll get back to it.

    Analyzing our HTTP server

    Well, then, let's analyze what's actually going on here.

    The first line requires the http module that ships with Node.js and makes it accessible through the variable http.

    We then call one of the functions the http module offers: createServer. This function returns an object, and this object has a method named listen, and takes a numeric value which indicates the port number our HTTP server is going to listen on.

    Please ignore for a second the function definition that follows the opening bracket of http.createServer.

    We could have written the code that starts our server and makes it listen at port 8888 like this:

    var http = require("http");
    
    var server = http.createServer();
    server.listen(8888);
    

    That would start an HTTP server listening at port 8888 and doing nothing else (not even answering any incoming requests).

    The really interesting (and, if your background is a more conservative language like PHP, odd looking) part is the function definition right there where you would expect the first parameter of the createServer() call.

    Turns out, this function definition IS the first (and only) parameter we are giving to the createServer() call. Because in JavaScript, functions can be passed around like any other value.

    Passing functions around

    You can, for example, do something like this:

    function say(word) {
      console.log(word);
    }
    
    function execute(someFunction, value) {
      someFunction(value);
    }
    
    execute(say, "Hello");
    

    Read this carefully! What we are doing here is, we pass the function say as the first parameter to the execute function. Not the return value of say, but say itself!

    Thus, say becomes the local variable someFunction within execute, and execute can call the function in this variable by issuing someFunction() (adding brackets).

    Of course, because say takes one parameter, execute can pass such a parameter when calling someFunction.

    We can, as we just did, pass a function as a parameter to another function by its name. But we don't have to take this indirection of first defining, then passing it - we can define and pass a function as a parameter to another function in-place:

    function execute(someFunction, value) {
      someFunction(value);
    }
    
    execute(function(word){ console.log(word) }, "Hello");
    

    We define the function we want to pass to execute right there at the place where execute expects its first parameter.

    This way, we don't even need to give the function a name, which is why this is called an anonymous function.

    This is a first glimpse at what I like to call "advanced" JavaScript, but let's take it step by step. For now, let's just accept that in JavaScript, we can pass a function as a parameter when calling another function. We can do this by assigning our function to a variable, which we then pass, or by defining the function to pass in-place.

    How function passing makes our HTTP server work
    var http = require("http");
    
    http.createServer(function(request, response) {
      response.writeHead(200, {"Content-Type": "text/plain"});
      response.write("Hello World");
      response.end();
    }).listen(8888);
    

    By now it should be clear what we are actually doing here: we pass the createServer function an anonymous function.

    We could achieve the same by refactoring our code to:

    var http = require("http");
    
    function onRequest(request, response) {
      response.writeHead(200, {"Content-Type": "text/plain"});
      response.write("Hello World");
      response.end();
    }
    
    http.createServer(onRequest).listen(8888);
    

    Maybe now is a good moment to ask: Why are we doing it that way?

    Event-driven asynchronous callbacks

    To understand why Node.js applications have to be written this way, we need to understand how Node.js executes our code. Node's approach isn't unique, but the underlying execution model is different from runtime environments like Python, Ruby, PHP or Java.

  • REPL TERMINAL ↓

    Node.js - REPL Terminal

    REPL stands for Read Eval Print Loop and it represents a computer environment like a window console or Unix/Linux shell where a command is entered and system responds with an output in interactive mode. Node.js or Node comes bundled with a REPL environment. It performs the following desired tasks.

    • Read - Reads user's input, parse the input into JavaScript data-structure and stores in memory.
    • Print - Prints the result
    • Loop - Loops the above command until user press ctrl-c twice.

    REPL feature of Node is very useful in experimenting with Node.js codes and to debug JavaScript codes.

    Starting REPL

    REPL can be started by simply running node on shell/console without any argument as follows.

    $ node

    You will see the REPL Command prompt > where you can type any Node.js command:

    $ node
    >
    Simple Expression

    Let's try simple mathematics at Node.js REPL command prompt:

    $ node
    > 1 + 3
    4
    > 1 + ( 2 * 3 ) - 4
    3
    >
    Use Variables

    You can make use variables to store values and print later like any conventional script. If var keyword is not used then value is stored in the variable and printed. Whereas if var keyword is used then value is stored but not printed. You can print variables usind console.log().

    $ node
    > x = 10
    10
    > var y = 10
    undefined
    > x + y
    20
    > console.log("Hello World")
    Hello World
    undefined
    Multiline Expression

    Node REPL supports multiline expression similar to JavaScript. Let's check the following do-while loop in action:

    $ node
    > var x = 0
    undefined
    > do {
    ... x++;
    ... console.log("x: " + x);
    ... } while ( x < 5 );
    x: 1
    x: 2
    x: 3
    x: 4
    x: 5
    undefined
    >

    ... comes automatically when you press enters after opening bracket. Node automatically checks the continuity of expressions.

    Underscore Variable

    You can use undercore _ to get the last result:

    $ node
    > var x = 10
    undefined
    > var y = 20
    undefined
    > x + y
    30
    > var sum = _
    undefined
    > console.log(sum)
    30
    undefined
    >

    REPL Commands

    • ctrl + c - terminate the current command.
    • ctrl + c twice - terminate the Node REPL.
    • ctrl + d - terminate the Node REPL.
    • cUp/Down Keys - see command history and modify previous commands.
    • tab Keys - list of current commands.
    • .help - list of all commands.
    • .breakc - exit from multiline expression.
    • .clear - exit from multiline expression
    • .save filename- save current Node REPL session to a file.
    • .load filename - load file content in current Node REPL session.
    Stopping REPL

    As mentioned above you will need to use ctrl + c twice command to come out of Node.js REPL.

    $ node
    >
    (^C again to quit)
    >
  • PACKAGE MANAGER (NPM) ↓

    Node.js - npm

    Node Package Manager (npm) provides following two main functionalities:

    • Online repositories for node.js packages/modules which are searchable on search.nodejs.org
    • Command line utility to install Node.js packages, do version management and dependency management of Node.js packages.

    npm comes bundled with Node.js installables after v0.6.3 version. To verify the same, open console and type following command and see the result:

    $ npm --version
    2.7.1

    If you are running old version of npm then its damn easy to update it to the latest version. Just use the following command from root:

    $ sudo npm install npm -g
    /usr/bin/npm -> /usr/lib/node_modules/npm/bin/npm-cli.js
    npm@2.7.1 /usr/lib/node_modules/npm
    Installing Modules using npm

    There is a simple syntax to install any Node.js module:

    $ npm install 

    For example, following is the command to install a famous Node.js web framework module called express:

    var express = require('express');
    Global vs Local installation

    By default, npm installs any dependency in the local mode. Here local mode refers to the package installation in node_modules directory lying in the folder where Node application is present. Locally deployed packages are accessible via require() method. For example when we installed express module, it created node_modules directory in the current directory where it installed express module.

    $ ls -l
    total 0
    drwxr-xr-x 3 root root 20 Mar 17 02:23 node_modules

    Alternatively you can use npm ls command to list down all the locally installed modules.

    Globally installed packages/dependencies are stored in system directory. Such dependencies can be used in CLI (Command Line Interface) function of any node.js but can not be imported using require() in Node application directly. Now Let's try installing express module using global installation.

    $ npm install express -g

    This will produce similar result but module will be installed globally. Here first line tells about the module version and its location where it is getting installed.

    express@4.12.2 /usr/lib/node_modules/express
    ├── merge-descriptors@1.0.0
    ├── utils-merge@1.0.0
    ├── cookie-signature@1.0.6
    ├── methods@1.1.1
    ├── fresh@0.2.4
    ├── cookie@0.1.2
    ├── escape-html@1.0.1
    ├── range-parser@1.0.2
    ├── content-type@1.0.1
    ├── finalhandler@0.3.3
    ├── vary@1.0.0
    ├── parseurl@1.3.0
    ├── content-disposition@0.5.0
    ├── path-to-regexp@0.1.3
    ├── depd@1.0.0
    ├── qs@2.3.3
    ├── on-finished@2.2.0 (ee-first@1.1.0)
    ├── etag@1.5.1 (crc@3.2.1)
    ├── debug@2.1.3 (ms@0.7.0)
    ├── proxy-addr@1.0.7 (forwarded@0.1.0, ipaddr.js@0.1.9)
    ├── send@0.12.1 (destroy@1.0.3, ms@0.7.0, mime@1.3.4)
    ├── serve-static@1.9.2 (send@0.12.2)
    ├── accepts@1.2.5 (negotiator@0.5.1, mime-types@2.0.10)
    └── type-is@1.6.1 (media-typer@0.3.0, mime-types@2.0.10)

    You can use following command to check all the modules installed globally:

    $ npm ls -g
    Using package.json

    package.json is present in the root directory of any Node application/module and is used to define the properties of a package. Let's open package.json of express package present innode_modules/express/

    {
      "name": "express",
      "description": "Fast, unopinionated, minimalist web framework",
      "version": "4.11.2",
      "author": {
        "name": "TJ Holowaychuk",
        "email": "tj@vision-media.ca"
      },
      "contributors": [
        {
          "name": "Aaron Heckmann",
          "email": "aaron.heckmann+github@gmail.com"
        },
        {
          "name": "Ciaran Jessup",
          "email": "ciaranj@gmail.com"
        },
        {
          "name": "Douglas Christopher Wilson",
          "email": "doug@somethingdoug.com"
        },
        {
          "name": "Guillermo Rauch",
          "email": "rauchg@gmail.com"
        },
        {
          "name": "Jonathan Ong",
          "email": "me@jongleberry.com"
        },
        {
          "name": "Roman Shtylman",
          "email": "shtylman+expressjs@gmail.com"
        },
        {
          "name": "Young Jae Sim",
          "email": "hanul@hanul.me"
        }
      ],
      "license": "MIT",
      "repository": {
        "type": "git",
        "url": "https://github.com/strongloop/express"
      },
      "homepage": "http://expressjs.com/",
      "keywords": [
        "express",
        "framework",
        "sinatra",
        "web",
        "rest",
        "restful",
        "router",
        "app",
        "api"
      ],
      "dependencies": {
        "accepts": "~1.2.3",
        "content-disposition": "0.5.0",
        "cookie-signature": "1.0.5",
        "debug": "~2.1.1",
        "depd": "~1.0.0",
        "escape-html": "1.0.1",
        "etag": "~1.5.1",
        "finalhandler": "0.3.3",
        "fresh": "0.2.4",
        "media-typer": "0.3.0",
        "methods": "~1.1.1",
        "on-finished": "~2.2.0",
        "parseurl": "~1.3.0",
        "path-to-regexp": "0.1.3",
        "proxy-addr": "~1.0.6",
        "qs": "2.3.3",
        "range-parser": "~1.0.2",
        "send": "0.11.1",
        "serve-static": "~1.8.1",
        "type-is": "~1.5.6",
        "vary": "~1.0.0",
        "cookie": "0.1.2",
        "merge-descriptors": "0.0.2",
        "utils-merge": "1.0.0"
      },
      "devDependencies": {
        "after": "0.8.1",
        "ejs": "2.1.4",
        "istanbul": "0.3.5",
        "marked": "0.3.3",
        "mocha": "~2.1.0",
        "should": "~4.6.2",
        "supertest": "~0.15.0",
        "hjs": "~0.0.6",
        "body-parser": "~1.11.0",
        "connect-redis": "~2.2.0",
        "cookie-parser": "~1.3.3",
        "express-session": "~1.10.2",
        "jade": "~1.9.1",
        "method-override": "~2.3.1",
        "morgan": "~1.5.1",
        "multiparty": "~4.1.1",
        "vhost": "~3.0.0"
      },
      "engines": {
        "node": ">= 0.10.0"
      },
      "files": [
        "LICENSE",
        "History.md",
        "Readme.md",
        "index.js",
        "lib/"
      ],
      "scripts": {
        "test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/",
        "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/",
        "test-tap": "mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/",
        "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/"
      },
      "gitHead": "63ab25579bda70b4927a179b580a9c580b6c7ada",
      "bugs": {
        "url": "https://github.com/strongloop/express/issues"
      },
      "_id": "express@4.11.2",
      "_shasum": "8df3d5a9ac848585f00a0777601823faecd3b148",
      "_from": "express@*",
      "_npmVersion": "1.4.28",
      "_npmUser": {
        "name": "dougwilson",
        "email": "doug@somethingdoug.com"
      },
      "maintainers": [
        {
          "name": "tjholowaychuk",
          "email": "tj@vision-media.ca"
        },
        {
          "name": "jongleberry",
          "email": "jonathanrichardong@gmail.com"
        },
        {
          "name": "shtylman",
          "email": "shtylman@gmail.com"
        },
        {
          "name": "dougwilson",
          "email": "doug@somethingdoug.com"
        },
        {
          "name": "aredridel",
          "email": "aredridel@nbtsc.org"
        },
        {
          "name": "strongloop",
          "email": "callback@strongloop.com"
        },
        {
          "name": "rfeng",
          "email": "enjoyjava@gmail.com"
        }
      ],
      "dist": {
        "shasum": "8df3d5a9ac848585f00a0777601823faecd3b148",
        "tarball": "http://registry.npmjs.org/express/-/express-4.11.2.tgz"
      },
      "directories": {},
      "_resolved": "https://registry.npmjs.org/express/-/express-4.11.2.tgz",
      "readme": "ERROR: No README data found!"
    }
    Attributes of Package.json
    • name - name of the package
    • version - version of the package
    • description - description of the package
    • homepage - homepage of the package
    • author - author of the package
    • contributors - name of the contributors to the package
    • dependencies - list of dependencies. npm automatically installs all the dependencies mentioned here in the node_module folder of the package.
    • repository - repository type and url of the package
    • main - entry point of the package
    • keywords - keywords
    Uninstalling a module

    Use following command to uninstall a Node.js module.

    $ npm uninstall express

    Once npm uninstall the package, you can verify by looking at the content of /node_modules/ directory or type the following command:

    $ npm ls
    Updating a module

    Update package.json and change the version of the dependency which to be updated and run the following command.

    $ npm update express

    Search a module

    Search package name using npm.

    $ npm search express
    Create a module

    Creation of module requires package.json to be generated. Let's generate package.json using npm, which will generate basic skeleton of the package.json.

    $ npm init
    This utility will walk you through creating a package.json file.
    It only covers the most common items, and tries to guess sane defaults.
    
    See 'npm help json' for definitive documentation on these fields
    and exactly what they do.
    
    Use 'npm install  --save' afterwards to install a package and
    save it as a dependency in the package.json file.
    
    Press ^C at any time to quit.
    name: (webmaster)

    You will need to provide all the required information about your module. YOu can take help from the above mentioned package.json file to understand the meanings of various information demanded. Once package.json is generated. Use the following command to register yourself with npm repository site using a valid email address.

    $ npm adduser
    Username: mcmohd
    Password:
    Email: (this IS public) abcd@gmail.com

    Now its time to publish your module:

    $ npm publish

    If everything is fine with your module, then it will be published in the reporsitory and will be accessible to install using npm like any other other Node.js module.

  • CALLBACKS CONCEPT ↓

    Callbacks Concept

    What is Callback?

    Callback is an asynchronous equivalent for a function. A callback function is called at the completion of a given task. Node makes heavy use of callbacks. All APIs of Node are written is such a way that they supports callbacks.

    For example, a function to read a file may start reading file and return the control to execution environment immidiately so that next instruction can be executed. Once file I/O is complete, it will call the callback function while passing the callback function, the content of the file as parameter. So there is no blocking or wait for File I/O. This makes Node.js highly scalable, as it can process high number of request without waiting for any function to return result.

    Blocking Code Example

    Create a text file named input.txt having following content

    Fastread is giving self learning content
    to teach the world in simple and easy way!!!!!

    Create a js file named main.js which has the following code:

    var fs = require("fs");
    
    var data = fs.readFileSync('input.txt');
    
    console.log(data.toString());
    console.log("Program Ended");

    Now run the main.js to see the result:

    $ node main.js

    Verify the Output

    Fastread is giving self learning content
    to teach the world in simple and easy way!!!!!
    Program Ended
    Non-Blocking Code Example

    Create a text file named input.txt having following content

    Fastread is giving self learning content
    to teach the world in simple and easy way!!!!!

    Update main.js file to have following code:

    var fs = require("fs");
    
    fs.readFile('input.txt', function (err, data) {
        if (err) return console.error(err);
        console.log(data.toString());
    });
    
    console.log("Program Ended");

    Now run the main.js to see the result:

    $ node main.js

    Verify the Output

    Program Ended
    Fastread is giving self learning content
    to teach the world in simple and easy way!!!!!

    These two examples explain the concept of blocking and non-blocking calls. First example shows that program blocks until it reads the file and then only it proceeds to end the program where as in second example, program does not wait for file reading but it just proceeded to print "Program Ended" and same time program without blocking continues reading the file.

    Thus, a blocking program executes very much in sequence and from programming point of view its easier to implement the logic but non-blocking programs does not execute in sequence, so in case a program needs to use any data to be processed, it should be kept with-in the same block to make it sequential execution.

  • EVENT LOOP ↓

    Event Loop

    Node js is a single threaded application but it support concurrency via concept of event and callbacks. As every API of Node js are asynchronous and being a single thread, it usesasync function calls to maintain the concurrency. Node uses observer pattern. Node thread keeps an event loop and whenever any task get completed, it fires the corresponding event which signals the event listener function to get executed.

    Event Driven Programming

    Node.js uses events heavily and it is also one of the reasons why Node.js is pretty fast compared to other similar technologies. As soon as Node starts its server, it simply initiates its variables, delcares functions and then simply waits for event to occur.

    In an event-driven application, there is generally a main loop that listens for events, and then triggers a callback function when one of those events is detected.

    node.js event loop

    While Events seems similar to what callbacks are. The difference lies in the fact that callback functions are called when an asynchronous function returns its result where as event handling works on the observer pattern. The functions which listens to events acts as Observers. Whenever an event gets fired, its listener function starts executing. Node.js has multiple in-built events available through events module and EventEmitter class which is used to bind events and event listeners as follows:

    // Import events module
    var events = require('events');
    // Create an eventEmitter object
    var eventEmitter = new events.EventEmitter();

    Following is the syntax to bind event handler with an event:

    // Bind event and even handler as follows
    eventEmitter.on('eventName', eventHandler);

    We can fire an event programatically as follows:

    // Fire an event 
    eventEmitter.emit('eventName');
    Example

    Create a js file named main.js having the following code:

    // Import events module
    var events = require('events');
    // Create an eventEmitter object
    var eventEmitter = new events.EventEmitter();
    
    // Create an event handler as follows
    var connectHandler = function connected() {
       console.log('connection succesful.');
      
       // Fire the data_received event 
       eventEmitter.emit('data_received');
    }
    
    // Bind the connection event with the handler
    eventEmitter.on('connection', connectHandler);
     
    // Bind the data_received event with the anonymous function
    eventEmitter.on('data_received', function(){
       console.log('data received succesfully.');
    });
    
    // Fire the connection event 
    eventEmitter.emit('connection');
    
    console.log("Program Ended.");

    Now let's try to run the above program as check the output:

    $ mnode main.js

    This will produce following result:

    connection succesful.
    data received succesfully.
    Program Ended.
    How Node Applications Work?

    In Node Application, any async function accepts a callback as a last parameter and the callback function accepts error as a first parameter. Let's revisit the previous example again. Create a text file named input.txt having following content

    Fastread is giving self learning content
    to teach the world in simple and easy way!!!!!

    Create a js file named main.js having the following code:

    var fs = require("fs");
    
    fs.readFile('input.txt', function (err, data) {
       if (err){
          console.log(err.stack);
          return;
       }
       console.log(data.toString());
    });
    console.log("Program Ended");

    Here fs.readFile() is a async function whose purpose is to read a file. If an error occurs during read of file, then err object will contain the corresponding error else data will contain the contents of the file. readFile passes err and data to callback function after file read operation is complete, which finally prints the content.

    Program Ended
    Fastread is giving self learning content
    to teach the world in simple and easy way!!!!!
  • EVENT EMITTER ↓

    Event Emitter

    Many objects in Node emit events for example a net.Server emits an event each time a peer connects to it, a fs.readStream emits an event when the file is opened. All objects which emit events are instances of events.EventEmitter.

    EventEmitter Class

    As we have seen in previous section, EventEmitter class lies in events module. It is accessibly via following syntax:

    // Import events module
    var events = require('events');
    // Create an eventEmitter object
    var eventEmitter = new events.EventEmitter();

    When an EventEmitter instance faces any error, it emits an 'error' event. When new listener is added, 'newListener' event is fired and when a listener is removed, 'removeListener' event is fired.

    EventEmitter provides multiple properties like on and emit. on property is used to bind a function with the event and emit is used to fire an event.

    Methods
    SN.Method & Description
    1 addListener(event, listener)
    Adds a listener to the end of the listeners array for the specified event. No checks are made to see if the listener has already been added. Multiple calls passing the same combination of event and listener will result in the listener being added multiple times. Returns emitter, so calls can be chained.
    2 on(event, listener)
    Adds a listener to the end of the listeners array for the specified event. No checks are made to see if the listener has already been added. Multiple calls passing the same combination of event and listener will result in the listener being added multiple times. Returns emitter, so calls can be chained.
    3 once(event, listener)
    Adds a one time listener for the event. This listener is invoked only the next time the event is fired, after which it is removed. Returns emitter, so calls can be chained.
    4 removeListener(event, listener)
    Remove a listener from the listener array for the specified event. Caution: changes array indices in the listener array behind the listener. removeListener will remove, at most, one instance of a listener from the listener array. If any single listener has been added multiple times to the listener array for the specified event, then removeListener must be called multiple times to remove each instance. Returns emitter, so calls can be chained.
    5 removeAllListeners([event])
    Removes all listeners, or those of the specified event. It's not a good idea to remove listeners that were added elsewhere in the code, especially when it's on an emitter that you didn't create (e.g. sockets or file streams). Returns emitter, so calls can be chained.
    6 setMaxListeners(n)
    By default EventEmitters will print a warning if more than 10 listeners are added for a particular event. This is a useful default which helps finding memory leaks. Obviously not all Emitters should be limited to 10. This function allows that to be increased. Set to zero for unlimited.
    7 listeners(event)
    Returns an array of listeners for the specified event.
    8 emit(event, [arg1], [arg2], [...])
    Execute each of the listeners in order with the supplied arguments. Returns true if event had listeners, false otherwise.
    Class Methods
    SN.Method & Description
    1 listenerCount(emitter, event)
    Return the number of listeners for a given event.
    Events
    SN.Events & Description
    1 newListener
    • event - String The event name
    • listener - Function The event handler function

    This event is emitted any time a listener is added. When this event is triggered, the listener may not yet have been added to the array of listeners for the event.
    2 removeListener
    • event - String The event name
    • listener - Function The event handler function

    This event is emitted any time someone removes a listener. When this event is triggered, the listener may not yet have been removed from the array of listeners for the event.
    Example

    Create a js file named main.js with the following Node.js code:

    var events = require('events');
    var eventEmitter = new events.EventEmitter();
    
    // listener #1
    var listner1 = function listner1() {
       console.log('listner1 executed.');
    }
    
    // listener #2
    var listner2 = function listner2() {
      console.log('listner2 executed.');
    }
    
    // Bind the connection event with the listner1 function
    eventEmitter.addListener('connection', listner1);
    
    // Bind the connection event with the listner2 function
    eventEmitter.on('connection', listner2);
    
    var eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection');
    console.log(eventListeners + " Listner(s) listening to connection event");
    
    // Fire the connection event 
    eventEmitter.emit('connection');
    
    // Remove the binding of listner1 function
    eventEmitter.removeListener('connection', listner1);
    console.log("Listner1 will not listen now.");
    
    // Fire the connection event 
    eventEmitter.emit('connection');
    
    eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection');
    console.log(eventListeners + " Listner(s) listening to connection event");
    
    console.log("Program Ended.");

    Now run the main.js to see the result:

    $ node main.js

    Verify the Output

    2 Listner(s) listening to connection event
    listner1 executed.
    listner2 executed.
    Listner1 will not listen now.
    listner2 executed.
    1 Listner(s) listening to connection event
    Program Ended.
  • BUFFERS ↓

    Buffers

    Pure JavaScript is Unicode friendly but not nice to binary data. When dealing with TCP streams or the file system, it's necessary to handle octet streams. Node provides Buffer class which provides instances to store raw data similar to an array of integers but corresponds to a raw memory allocation outside the V8 heap.

    Buffer class is a global class and can be accessed in application without importing buffer module.

    Creating Buffers

    Node Buffer can be constructed in a variety of ways.

    Method 1

    Following is the syntax to create an uninitiated Buffer of 10 octets:

    var buf = new Buffer(10);

    Method 2

    Following is the syntax to create a Buffer from a given array:

    var buf = new Buffer([10, 20, 30, 40, 50]);

    Method 3

    Following is the syntax to create a Buffer from a given string and optionally encoding type:

    var buf = new Buffer("Simply Easy Learning", "utf-8");

    Though "utf8" is the default encoding but you can use either of the encodings "ascii", "utf8", "utf16le", "ucs2", "base64" or "hex".

    Writing to Buffers

    Syntax

    Following is the syntax of the method to write into a Node Buffer:

    buf.write(string[, offset][, length][, encoding])
    Parameters

    Here is the description of the parameters used:

    • string - This is string data to be written to buffer.
    • offset - This is the index of the buffer to start writing at. Default value is 0.
    • length - This is the number of bytes to write. Defaults to buffer.length
    • encoding - Encoding to use. 'utf8' is the default encoding
    Return Value

    This method returns number of octets written. If there is not enough space in the buffer to fit the entire string, it will write a part of the string.

    Example
    buf = new Buffer(256);
    len = buf.write("Simply Easy Learning");
    
    console.log("Octets written : "+  len);

    When above program is executed, it produces following result:

    Octets written : 20
    Reading from Buffers

    Syntax

    Following is the syntax of the method to read data from a Node Buffer:

    buf.toString([encoding][, start][, end])

    Parameters

    Here is the description of the parameters used:

    • encoding - Encoding to use. 'utf8' is the default encoding
    • start - Beginning index to start reading, defaults to 0.
    • end - End index to end reading, defaults is complete buffer.

    Return Value

    This method decodes and returns a string from buffer data encoded using the specified character set encoding.

    Example
    buf = new Buffer(26);
    for (var i = 0 ; i < 26 ; i++) {
      buf[i] = i + 97;
    }
    
    console.log( buf.toString('ascii'));       // outputs: abcdefghijklmnopqrstuvwxyz
    console.log( buf.toString('ascii',0,5));   // outputs: abcde
    console.log( buf.toString('utf8',0,5));    // outputs: abcde
    console.log( buf.toString(undefined,0,5)); // encoding defaults to 'utf8', outputs abcde

    When above program is executed, it produces following result:

    abcdefghijklmnopqrstuvwxyz
    abcde
    abcde
    abcde
    Convert Buffer to JSON

    Syntax

    Following is the syntax of the method to convert a Node Buffer into JSON object:

    buf.toJSON()

    Return Value

    This method returns a JSON-representation of the Buffer instance.

    Example
    var buf = new Buffer('Simply Easy Learning');
    var json = buf.toJSON(buf);
    
    console.log(json);

    When above program is executed, it produces following result:

    [ 83, 105, 109, 112, 108, 121, 32, 69, 97, 115, 121, 32, 76, 101, 97, 114, 110, 105, 110, 103 ]
    Concatenate Buffers

    Syntax

    Following is the syntax of the method to concatenate Node buffers to a single Node Buffer:

    Buffer.concat(list[, totalLength])
    Parameters

    Here is the description of the parameters used:

    • list - Array List of Buffer objects to be concatenated
    • totalLength - This is the total length of the buffers when concatenated
    Return Value

    This method returns a Buffer instance.

    Example
    var buffer1 = new Buffer('TutorialsPoint ');
    var buffer2 = new Buffer('Simply Easy Learning');
    var buffer3 = Buffer.concat([buffer1,buffer2]);
    console.log("buffer3 content: " + buffer3.toString());

    When above program is executed, it produces following result:

    buffer3 content: TutorialsPoint Simply Easy Learning
    Compare Buffers
    Syntax

    Following is the syntax of the method to compare two Node buffers:

    buf.compare(otherBuffer);
    Parameters

    Here is the description of the parameters used:

    • otherBuffer
    • - This is the other buffer which will be compared with buf
    Return Value

    Returns a number indicating whether this comes before or after or is the same as the otherBuffer in sort order.

    Example
    var buffer1 = new Buffer('ABC');
    var buffer2 = new Buffer('ABCD');
    var result = buffer1.compare(buffer2);
    
    if(result < 0) {
       console.log(buffer1 +" comes before " + buffer2);
    }else if(result == 0){
       console.log(buffer1 +" is same as " + buffer2);
    }else {
       console.log(buffer1 +" comes after " + buffer2);
    }

    When above program is executed, it produces following result:

    ABC comes before ABCD
    Copy Buffer
    Syntax

    Following is the syntax of the method to copy a node buffer:

    buf.copy(targetBuffer[, targetStart][, sourceStart][, sourceEnd])
    Parameters

    Here is the description of the parameters used:

    • targetBuffer - Buffer object where buffer will be copied.
    • targetStart - Number, Optional, Default: 0
    • sourceStart - Number, Optional, Default: 0
    • sourceEnd - Number, Optional, Default: buffer.length
    Return Value

    No return value. Copies data from a region of this buffer to a region in the target buffer even if the target memory region overlaps with the source. If undefined the targetStart and sourceStart parameters default to 0 while sourceEnd defaults to buffer.length.

    Example
    var buffer1 = new Buffer('ABC');
    //copy a buffer
    var buffer2 = new Buffer(3);
    buffer1.copy(buffer2);
    console.log("buffer2 content: " + buffer2.toString());

    When above program is executed, it produces following result:

    buffer2 content: ABC
    Slice Buffer
    Syntax

    Following is the syntax of the method to get a sub-buffer of a node buffer:

    buf.slice([start][, end])
    Parameters

    Here is the description of the parameters used:

    • start - Number, Optional, Default: 0
    • end - Number, Optional, Default: buffer.length
    Return Value

    Returns a new buffer which references the same memory as the old, but offset and cropped by the start (defaults to 0) and end (defaults to buffer.length) indexes. Negative indexes start from the end of the buffer.

    Example
    var buffer1 = new Buffer('TutorialsPoint');
    //slicing a buffer
    var buffer2 = buffer1.slice(0,9);
    console.log("buffer2 content: " + buffer2.toString());

    When above program is executed, it produces following result:

    buffer2 content: Tutorials
    Buffer Length
    Syntax

    Following is the syntax of the method to get a sub-buffer of a node buffer:Following is the syntax of the method to get a size of a node buffer in bytes:

    buf.length;
    Return Value

    Returns a size of buffer in bytes.

    Example
    var buffer = new Buffer('TutorialsPoint');
    //length of the buffer
    console.log("buffer length: " + buffer.length);

    When above program is executed, it produces following result:

    buffer length: 14
    Methods Reference

    Following is a reference of Buffers module available in Node.js. For a further detail you can refer to official documentation.

    SN.Method & Description
    1 new Buffer(size)
    Allocates a new buffer of size octets. Note, size must be no more than kMaxLength. Otherwise, a RangeError will be thrown here.
    2 new Buffer(buffer)
    Copies the passed buffer data onto a new Buffer instance.
    3 new Buffer(str[, encoding])
    Allocates a new buffer containing the given str. encoding defaults to 'utf8'.
    4 buf.length
    Returns the size of the buffer in bytes. Note that this is not necessarily the size of the contents. length refers to the amount of memory allocated for the buffer object. It does not change when the contents of the buffer are changed.
    5 buf.write(string[, offset][, length][, encoding])
    Writes string to the buffer at offset using the given encoding. offset defaults to 0, encoding defaults to 'utf8'. length is the number of bytes to write. Returns number of octets written.
    6 buf.writeUIntLE(value, offset, byteLength[, noAssert])
    Writes value to the buffer at the specified offset and byteLength. Supports up to 48 bits of accuracy. Set noAssert to true to skip validation of value and offset. Defaults to false.
    7 buf.writeUIntBE(value, offset, byteLength[, noAssert])
    Writes value to the buffer at the specified offset and byteLength. Supports up to 48 bits of accuracy. Set noAssert to true to skip validation of value and offset. Defaults to false.
    8 buf.writeIntLE(value, offset, byteLength[, noAssert])
    Writes value to the buffer at the specified offset and byteLength. Supports up to 48 bits of accuracy. Set noAssert to true to skip validation of value and offset. Defaults to false.
    9 buf.writeIntBE(value, offset, byteLength[, noAssert])
    Writes value to the buffer at the specified offset and byteLength. Supports up to 48 bits of accuracy. Set noAssert to true to skip validation of value and offset. Defaults to false.
    10 buf.readUIntLE(offset, byteLength[, noAssert])
    A generalized version of all numeric read methods. Supports up to 48 bits of accuracy.Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    11 buf.readUIntBE(offset, byteLength[, noAssert])
    A generalized version of all numeric read methods. Supports up to 48 bits of accuracy.Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    12 buf.readIntLE(offset, byteLength[, noAssert])
    A generalized version of all numeric read methods. Supports up to 48 bits of accuracy.Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    13 buf.readIntBE(offset, byteLength[, noAssert])
    A generalized version of all numeric read methods. Supports up to 48 bits of accuracy.Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    14 buf.toString([encoding][, start][, end])
    Decodes and returns a string from buffer data encoded using the specified character set encoding.
    15 buf.toJSON()
    Returns a JSON-representation of the Buffer instance. JSON.stringify implicitly calls this function when stringifying a Buffer instance.
    16 buf[index]
    Get and set the octet at index. The values refer to individual bytes, so the legal range is between 0x00 and 0xFF hex or 0 and 255.
    17 buf.equals(otherBuffer)
    Returns a boolean of whether this and otherBuffer have the same bytes.
    18 buf.compare(otherBuffer)
    Returns a number indicating whether this comes before or after or is the same as the otherBuffer in sort order.
    19 buf.copy(targetBuffer[, targetStart][, sourceStart][, sourceEnd])
    Copies data from a region of this buffer to a region in the target buffer even if the target memory region overlaps with the source. If undefined the targetStart and sourceStart parameters default to 0 while sourceEnd defaults to buffer.length.
    20 buf.slice([start][, end])
    Returns a new buffer which references the same memory as the old, but offset and cropped by the start (defaults to 0) and end (defaults to buffer.length) indexes. Negative indexes start from the end of the buffer.
    21 buf.readUInt8(offset[, noAssert])
    Reads an unsigned 8 bit integer from the buffer at the specified offset. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    22 buf.readUInt16LE(offset[, noAssert])
    Reads an unsigned 16 bit integer from the buffer at the specified offset with specified endian format. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    23 buf.readUInt16BE(offset[, noAssert])
    Reads an unsigned 16 bit integer from the buffer at the specified offset with specified endian format. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    24 buf.readUInt32LE(offset[, noAssert])
    Reads an unsigned 32 bit integer from the buffer at the specified offset with specified endian format. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    25 buf.readUInt32BE(offset[, noAssert])
    Reads an unsigned 32 bit integer from the buffer at the specified offset with specified endian format. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    26 buf.readInt8(offset[, noAssert])
    Reads a signed 8 bit integer from the buffer at the specified offset. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    27 buf.readInt16LE(offset[, noAssert])
    Reads a signed 16 bit integer from the buffer at the specified offset with specified endian format. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    28 buf.readInt16BE(offset[, noAssert])/strong>
    Reads a signed 16 bit integer from the buffer at the specified offset with specified endian format. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    29 buf.readInt32LE(offset[, noAssert])
    Reads a signed 32 bit integer from the buffer at the specified offset with specified endian format. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    30 buf.readInt32BE(offset[, noAssert])
    Reads a signed 32 bit integer from the buffer at the specified offset with specified endian format. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    31 buf.readFloatLE(offset[, noAssert])
    Reads a 32 bit float from the buffer at the specified offset with specified endian format. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    32 buf.readFloatBE(offset[, noAssert])
    Reads a 32 bit float from the buffer at the specified offset with specified endian format. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    33 buf.readDoubleLE(offset[, noAssert])
    Reads a 64 bit double from the buffer at the specified offset with specified endian format. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    34 buf.readDoubleBE(offset[, noAssert])
    Reads a 64 bit double from the buffer at the specified offset with specified endian format. Set noAssert to true to skip validation of offset. This means that offset may be beyond the end of the buffer. Defaults to false.
    35 buf.writeUInt8(value, offset[, noAssert])
    Writes value to the buffer at the specified offset. Note, value must be a valid unsigned 8 bit integer. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    36 buf.writeUInt16LE(value, offset[, noAssert])
    Writes value to the buffer at the specified offset with specified endian format. Note, value must be a valid unsigned 16 bit integer. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    37 buf.writeUInt16BE(value, offset[, noAssert])
    Writes value to the buffer at the specified offset with specified endian format. Note, value must be a valid unsigned 16 bit integer. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    38 buf.writeUInt32LE(value, offset[, noAssert])
    Writes value to the buffer at the specified offset with specified endian format. Note, value must be a valid unsigned 32 bit integer. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    39 buf.writeUInt32BE(value, offset[, noAssert])
    Writes value to the buffer at the specified offset with specified endian format. Note, value must be a valid unsigned 32 bit integer. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    40 buf.writeInt8(value, offset[, noAssert])
    Writes value to the buffer at the specified offset with specified endian format. Note, value must be a valid signed 8 bit integer. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    41 buf.writeInt16LE(value, offset[, noAssert])
    Writes value to the buffer at the specified offset with specified endian format. Note, value must be a valid signed 16 bit integer. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    42 buf.writeInt16BE(value, offset[, noAssert])
    Writes value to the buffer at the specified offset with specified endian format. Note, value must be a valid signed 16 bit integer. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    43 buf.writeInt32LE(value, offset[, noAssert])
    Writes value to the buffer at the specified offset with specified endian format. Note, value must be a valid signed 32 bit integer. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    44 buf.writeInt32BE(value, offset[, noAssert])
    Writes value to the buffer at the specified offset with specified endian format. Note, value must be a valid signed 32 bit integer. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    45 buf.writeFloatLE(value, offset[, noAssert])
    Writes value to the buffer at the specified offset with specified endian format. Note, value must be a valid 32 bit float. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    46 buf.writeFloatBE(value, offset[, noAssert])
    Writes value to the buffer at the specified offset with specified endian format. Note, value must be a valid 32 bit float. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    47 buf.writeDoubleLE(value, offset[, noAssert])
    Writes value to the buffer at the specified offset with specified endian format. Note, value must be a valid 64 bit double. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    48 buf.writeDoubleBE(value, offset[, noAssert])
    Writes value to the buffer at the specified offset with specified endian format. Note, value must be a valid 64 bit double. Set noAssert to true to skip validation of value and offset. This means that value may be too large for the specific function and offset may be beyond the end of the buffer leading to the values being silently dropped. This should not be used unless you are certain of correctness. Defaults to false.
    49 buf.fill(value[, offset][, end])
    Fills the buffer with the specified value. If the offset (defaults to 0) and end (defaults to buffer.length) are not given it will fill the entire buffer.
    Class Methods
    SN.Method & Description
    1 Buffer.isEncoding(encoding)
    Returns true if the encoding is a valid encoding argument, or false otherwise.
    2 Buffer.isBuffer(obj)
    Tests if obj is a Buffer.
    3 Buffer.byteLength(string[, encoding])
    Gives the actual byte length of a string. encoding defaults to 'utf8'. This is not the same as String.prototype.length since that returns the number of characters in a string.
    4 Buffer.concat(list[, totalLength])
    Returns a buffer which is the result of concatenating all the buffers in the list together.
    5 Buffer.compare(buf1, buf2)
    The same as buf1.compare(buf2). Useful for sorting an Array of Buffers.
  • STREAMS ↓

    Streams

    What are Streams?

    Streams are objects that let you read data from a source or write data to a destination in continous fashion. In Node.js, there are four types of streams.

    • Readable - Stream which is used for read operation.
    • Writable - Stream which is used for write operation.
    • Duplex - Stream which can be used for both read and write operation.
    • Transform - A type of duplex stream where the output is computed based on input.

    Each type of Stream is an EventEmitter instance and throws several events at different instance of times. For example, some of the commonly used events are:

    • data - This event is fired when there is data is available to read.
    • end - This event is fired when there is no more data to read.
    • error - This event is fired when there is any error receiving or writing data.
    • finish - This event is fired when all data has been flushed to underlying system

    This tutorial will give you understanding on commonly used operations on Streams.

    Reading from stream

    Create a text file named input.txt having following content

    Fastread is giving self learning content
    to teach the world in simple and easy way!!!!!

    Create a js file named main.js which has the following code:

    var fs = require("fs");
    var data = '';
    
    // Create a readable stream
    var readerStream = fs.createReadStream('input.txt');
    
    // Set the encoding to be utf8. 
    readerStream.setEncoding('UTF8');
    
    // Handle stream events --> data, end, and error
    readerStream.on('data', function(chunk) {
       data += chunk;
    });
    
    readerStream.on('end',function(){
       console.log(data);
    });
    
    readerStream.on('error', function(err){
       console.log(err.stack);
    });
    
    console.log("Program Ended");

    Now run the main.js to see the result:

    $ node main.js

    Verify the Output

    Program Ended
    Fastread is giving self learning content
    to teach the world in simple and easy way!!!!!
    Writing to stream

    Create a js file named main.js which has the following code:

    var fs = require("fs");
    var data = 'Simply Easy Learning';
    
    // Create a writable stream
    var writerStream = fs.createWriteStream('output.txt');
    
    // Write the data to stream with encoding to be utf8
    writerStream.write(data,'UTF8');
    
    // Mark the end of file
    writerStream.end();
    
    // Handle stream events --> finish, and error
    writerStream.on('finish', function() {
        console.log("Write completed.");
    });
    
    writerStream.on('error', function(err){
       console.log(err.stack);
    });
    
    console.log("Program Ended");

    Now run the main.js to see the result:

    $ node main.js

    Verify the Output

    Program Ended
    Write completed.

    Now open output.txt created in your current directory and verify the following content available in output.txt file.

    Simply Easy Learning
    Piping streams

    Piping is a mechanism where we provide output of one stream as the input to another stream. It is normally used to get data from one stream and to pass output of that stream to another stream. There is no limit on piping operations. Now we'll show a piping example for reading from one file and writing it to another file.

    Create a js file named main.js which has the following code:

    var fs = require("fs");
    
    // Create a readable stream
    var readerStream = fs.createReadStream('input.txt');
    
    // Create a writable stream
    var writerStream = fs.createWriteStream('output.txt');
    
    // Pipe the read and write operations
    // read input.txt and write data to output.txt
    readerStream.pipe(writerStream);
    
    console.log("Program Ended");

    Now run the main.js to see the result:

    $ node main.js

    Verify the Output

    Program Ended

    Open output.txt created in your current directory and verify the following content available in output.txt file.

    Fastread is giving self learning content to teach the world in simple and easy way!!!!!
    Chaining streams

    Chanining is a mechanism to connect output of one stream to another stream and create a chain of multiple stream operations. It is normally used with piping operations. Now we'll use the piping and chaining to first compress a file and then decompress the same.

    Create a js file named main.js which has the following code:

    var fs = require("fs");
    var zlib = require('zlib');
    
    // Compress the file input.txt to input.txt.gz
    fs.createReadStream('input.txt')
      .pipe(zlib.createGzip())
      .pipe(fs.createWriteStream('input.txt.gz'));
      
    console.log("File Compressed.");

    Now run the main.js to see the result:

    $ node main.js

    Verify the Output

    File Compressed.

    You will find that input.txt file has been compressed and it created a file input.txt.gz in the current directory. Now let's try to decompress the same file using the following code.

    var fs = require("fs");
    var zlib = require('zlib');
    
    // Decompress the file input.txt.gz to input.txt
    fs.createReadStream('input.txt.gz')
      .pipe(zlib.createGunzip())
      .pipe(fs.createWriteStream('input.txt'));
      
    console.log("File Decompressed.");

    Now run the main.js to see the result:

    $ node main.js

    Verify the Output

    File Decompressed.
  • FILE SYSTEM ↓

    File System

    Node implements File I/O using simple wrappers around standard POSIX functions. Node File System (fs) module can be imported using following syntax:

    var fs = require("fs")

    Synchronous vs Asynchronous

    Every method in fs module have synchronous as well as asynchronous form. Asynchronous methods takes a last parameter as completion function callback and first parameter of the callback function is error. It is preferred to use asynchronous method instead of synchronous method as former never block the program execution where as the second one does.

    Example

    Create a text file named input.txt having following content

    Fastread is giving self learning content
    to teach the world in simple and easy way!!!!!
    

    Let us create a js file named main.js having the following code.

    var fs = require("fs");
    
    // Asynchronous read
    fs.readFile('input.txt', function (err, data) {
       if (err) {
           return console.error(err);
       }
       console.log("Asynchronous read: " + data.toString());
    });
    
    // Synchronous read
    var data = fs.readFileSync('input.txt');
    console.log("Synchronous read: " + data.toString());
    
    console.log("Program Ended");
    

    Now run the main.js to see the result:

    $ node main.js
    

    Verify the Output

    Synchronous read: Fastread is giving self learning content
    to teach the world in simple and easy way!!!!!
    
    Program Ended
    Asynchronous read: Fastread is giving self learning content
    to teach the world in simple and easy way!!!!!
    

    Following section will give good examples on major File I/O methods.

    Open a File

    Syntax

    Following is the syntax of the method to open a file in asynchronous mode:

    fs.open(path, flags[, mode], callback)
    

    Parameters

    Here is the description of the parameters used:

    • path - This is string having file name including path.

    • flags - Flag tells the behavior of the file to be opened. All possible values have been mentioned below.

    • mode - This sets the file mode (permission and sticky bits), but only if the file was created. It defaults to 0666, readable and writeable.

    • callback - This is the callback function which gets two arguments (err, fd).

    Flags

    Flags for read/write operations are:

    FlagDescription
    rOpen file for reading. An exception occurs if the file does not exist.
    r+ Open file for reading and writing. An exception occurs if the file does not exist.
    rsOpen file for reading in synchronous mode.
    rs+Open file for reading and writing, telling the OS to open it synchronously. See notes for 'rs' about using this with caution.
    wOpen file for writing. The file is created (if it does not exist) or truncated (if it exists).
    wxLike 'w' but fails if path exists.
    w+Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists).
    wx+Like 'w+' but fails if path exists.
    aOpen file for appending. The file is created if it does not exist.
    axLike 'a' but fails if path exists.
    a+Open file for reading and appending. The file is created if it does not exist.
    ax+Like 'a+' but fails if path exists.

    Example

    Let us create a js file named main.js having the following code to open a file input.txt for reading and writing.

    var fs = require("fs");
    
    // Asynchronous - Opening File
    console.log("Going to open file!");
    fs.open('input.txt', 'r+', function(err, fd) {
       if (err) {
           return console.error(err);
       }
      console.log("File opened successfully!");     
    });
    

    Now run the main.js to see the result:

    $ node main.js
    

    Verify the Output

    Going to open file!
    File opened successfully!
    

    Get File information

    Syntax

    Following is the syntax of the method to get the information about a file:

    fs.stat(path, callback)
    

    Parameters

    Here is the description of the parameters used:

    • path - This is string having file name including path.

    • callback - This is the callback function which gets two arguments (err, stats) where stats is an object of fs.Stats type which is printed below in the example.

    Apart from the important attributes which are printed below in the example, there are number of useful methods available in fs.Stats class which can be used to check file type. These methods are given in the following table.

    MethodDescription
    stats.isFile()Returns true if file type of a simple file.
    stats.isDirectory()Returns true if file type of a directory.
    stats.isBlockDevice()Returns true if file type of a block device.
    stats.isCharacterDevice()Returns true if file type of a character device.
    stats.isSymbolicLink()Returns true if file type of a symbolic link.
    stats.isFIFO()Returns true if file type of a FIFO.
    stats.isSocket()Returns true if file type of asocket.

    Example

    Let us create a js file named main.js having the following code:

    var fs = require("fs");
    
    console.log("Going to get file info!");
    fs.stat('input.txt', function (err, stats) {
       if (err) {
           return console.error(err);
       }
       console.log(stats);
       console.log("Got file info successfully!");
       
       // Check file type
       console.log("isFile ? " + stats.isFile());
       console.log("isDirectory ? " + stats.isDirectory());    
    });
    

    Now run the main.js to see the result:

    $ node main.js
    

    Verify the Output

    Going to get file info!
    { dev: 1792,
      mode: 33188,
      nlink: 1,
      uid: 48,
      gid: 48,
      rdev: 0,
      blksize: 4096,
      ino: 4318127,
      size: 97,
      blocks: 8,
      atime: Sun Mar 22 2015 13:40:00 GMT-0500 (CDT),
      mtime: Sun Mar 22 2015 13:40:57 GMT-0500 (CDT),
      ctime: Sun Mar 22 2015 13:40:57 GMT-0500 (CDT) }
    Got file info successfully!
    isFile ? true
    isDirectory ? false
    

    Writing File

    Syntax

    Following is the syntax of one of the methods to write into a file:

    fs.writeFile(filename, data[, options], callback)
    

    This method will over-write the file if file already exists. If you want to write into an existing file then you should use another method available.

    Parameters

    Here is the description of the parameters used:

    • path - This is string having file name including path.

    • data - This is the String or Buffer to be written into the file.

    • options - The third parameter is an object which will hold {encoding, mode, flag}. By default encoding is utf8, mode is octal value 0666 and flag is 'w'

    • callback - This is the callback function which gets a single parameter err and used to to return error in case of any writing error.

    Example

    Let us create a js file named main.js having the following code:

    var fs = require("fs");
    
    console.log("Going to write into existing file");
    fs.writeFile('input.txt', 'Simply Easy Learning!',  function(err) {
       if (err) {
           return console.error(err);
       }
       console.log("Data written successfully!");
       console.log("Let's read newly written data");
       fs.readFile('input.txt', function (err, data) {
          if (err) {
             return console.error(err);
          }
          console.log("Asynchronous read: " + data.toString());
       });
    });
    

    Now run the main.js to see the result:

    $ node main.js
    

    Verify the Output

    Going to write into existing file
    Data written successfully!
    Let's read newly written data
    Asynchronous read: Simply Easy Learning!
    

    Reading File

    Syntax

    Following is the syntax of one of the methods to read from a file:

    fs.read(fd, buffer, offset, length, position, callback)
    

    This method will use file descriptor to read the file, if you want to read file using file name directly then you should use another method available.

    Parameters

    Here is the description of the parameters used:

    • fd - This is the file descriptor returned by file fs.open() method.

    • buffer - This is the buffer that the data will be written to.

    • offset - This is the offset in the buffer to start writing at.

    • length - This is an integer specifying the number of bytes to read.

    • position - This is an integer specifying where to begin reading from in the file. If position is null, data will be read from the current file position.

    • callback - This is the callback function which gets the three arguments, (err, bytesRead, buffer).

    Example

    Let us create a js file named main.js having the following code:

    var fs = require("fs");
    var buf = new Buffer(1024);
    
    console.log("Going to open an existing file");
    fs.open('input.txt', 'r+', function(err, fd) {
       if (err) {
           return console.error(err);
       }
       console.log("File opened successfully!");
       console.log("Going to read the file");
       fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
          if (err){
             console.log(err);
          }
          console.log(bytes + " bytes read");
          
          // Print only read bytes to avoid junk.
          if(bytes > 0){
             console.log(buf.slice(0, bytes).toString());
          }
       });
    });
    

    Now run the main.js to see the result:

    $ node main.js
    

    Verify the Output

    Going to open an existing file
    File opened successfully!
    Going to read the file
    97 bytes read
    Fastread is giving self learning content
    to teach the world in simple and easy way!!!!!
    

    Closing File

    Syntax

    Following is the syntax of one of the methods to close an opened file:

    fs.close(fd, callback)
    

    Parameters

    Here is the description of the parameters used:

    • fd - This is the file descriptor returned by file fs.open() method.

    • callback - This is the callback function which gets no arguments other than a possible exception are given to the completion callback.

    Example

    Let us create a js file named main.js having the following code:

    var fs = require("fs");
    var buf = new Buffer(1024);
    
    console.log("Going to open an existing file");
    fs.open('input.txt', 'r+', function(err, fd) {
       if (err) {
           return console.error(err);
       }
       console.log("File opened successfully!");
       console.log("Going to read the file");
       fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
          if (err){
             console.log(err);
          }
    
          // Print only read bytes to avoid junk.
          if(bytes > 0){
             console.log(buf.slice(0, bytes).toString());
          }
    
          // Close the opened file.
          fs.close(fd, function(err){
             if (err){
                console.log(err);
             } 
             console.log("File closed successfully.");
          });
       });
    });
    

    Now run the main.js to see the result:

    $ node main.js
    

    Verify the Output

    Going to open an existing file
    File opened successfully!
    Going to read the file
    Fastread is giving self learning content
    to teach the world in simple and easy way!!!!!
    
    File closed successfully.
    

    Truncate File

    Syntax

    Following is the syntax of the method to truncate an opened file:

    fs.ftruncate(fd, len, callback)
    

    Parameters

    Here is the description of the parameters used:

    • fd - This is the file descriptor returned by file fs.open() method.

    • len - This is the length of the file after which file will be truncated.

    • callback - This is the callback function which gets no arguments other than a possible exception are given to the completion callback.

    Example

    Let us create a js file named main.js having the following code:

    var fs = require("fs");
    var buf = new Buffer(1024);
    
    console.log("Going to open an existing file");
    fs.open('input.txt', 'r+', function(err, fd) {
       if (err) {
           return console.error(err);
       }
       console.log("File opened successfully!");
       console.log("Going to truncate the file after 10 bytes");
       
       // Truncate the opened file.
       fs.ftruncate(fd, 10, function(err){
          if (err){
             console.log(err);
          } 
          console.log("File truncated successfully.");
          console.log("Going to read the same file"); 
          fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
             if (err){
                console.log(err);
             }
    
             // Print only read bytes to avoid junk.
             if(bytes > 0){
                console.log(buf.slice(0, bytes).toString());
             }
    
             // Close the opened file.
             fs.close(fd, function(err){
                if (err){
                   console.log(err);
                } 
                console.log("File closed successfully.");
             });
          });
       });
    });
    

    Now run the main.js to see the result:

    $ node main.js
    

    Verify the Output

    Going to open an existing file
    File opened successfully!
    Going to truncate the file after 10 bytes
    File truncated successfully.
    Going to read the same file
    Tutorials 
    File closed successfully.
    

    Delete File

    Syntax

    Following is the syntax of the method to delete a file:

    fs.unlink(path, callback)
    

    Parameters

    Here is the description of the parameters used:

    • path - This is the file name including path.

    • callback - This is the callback function which gets no arguments other than a possible exception are given to the completion callback.

    Example

    Let us create a js file named main.js having the following code:

    var fs = require("fs");
    
    console.log("Going to delete an existing file");
    fs.unlink('input.txt', function(err) {
       if (err) {
           return console.error(err);
       }
       console.log("File deleted successfully!");
    });
    

    Now run the main.js to see the result:

    $ node main.js
    

    Verify the Output

    Going to delete an existing file
    File deleted successfully!
    

    Create Directory

    Syntax

    Following is the syntax of the method to create a directory:

    fs.mkdir(path[, mode], callback)
    

    Parameters

    Here is the description of the parameters used:

    • path - This is the directory name including path.

    • mode - This is the directory permission to be set. Defaults to 0777.

    • callback - This is the callback function which gets no arguments other than a possible exception are given to the completion callback.

    Example

    Let us create a js file named main.js having the following code:

    var fs = require("fs");
    
    console.log("Going to create directory /tmp/test");
    fs.mkdir('/tmp/test',function(err){
       if (err) {
           return console.error(err);
       }
       console.log("Directory created successfully!");
    });
    

    Now run the main.js to see the result:

    $ node main.js
    

    Verify the Output

    Going to create directory /tmp/test
    Directory created successfully!
    

    Read Directory

    Syntax

    Following is the syntax of the method to read a directory:

    fs.readdir(path, callback)
    

    Parameters

    Here is the description of the parameters used:

    • path - This is the directory name including path.

    • callback - This is the callback function which gets two arguments (err, files) where files is an array of the names of the files in the directory excluding '.' and '..'.

    Example

    Let us create a js file named main.js having the following code:

    var fs = require("fs");
    
    console.log("Going to read directory /tmp");
    fs.readdir("/tmp/",function(err, files){
       if (err) {
           return console.error(err);
       }
       files.forEach( function (file){
           console.log( file );
       });
    });
    

    Now run the main.js to see the result:

    $ node main.js
    

    Verify the Output

    Going to read directory /tmp
    ccmzx99o.out
    ccyCSbkF.out
    employee.ser
    hsperfdata_apache
    test
    test.txt
    

    Remove Directory

    Syntax

    Following is the syntax of the method to remove a directory:

    fs.rmdir(path, callback)
    

    Parameters

    Here is the description of the parameters used:

    • path - This is the directory name including path.

    • callback - This is the callback function which gets no arguments other than a possible exception are given to the completion callback.

    Example

    Let us create a js file named main.js having the following code:

    var fs = require("fs");
    
    console.log("Going to delete directory /tmp/test");
    fs.rmdir("/tmp/test",function(err){
       if (err) {
           return console.error(err);
       }
       console.log("Going to read directory /tmp");
       fs.readdir("/tmp/",function(err, files){
          if (err) {
              return console.error(err);
          }
          files.forEach( function (file){
              console.log( file );
          });
       });
    });
    

    Now run the main.js to see the result:

    $ node main.js
    

    Verify the Output

    Going to read directory /tmp
    ccmzx99o.out
    ccyCSbkF.out
    employee.ser
    hsperfdata_apache
    test.txt
    

    Methods Reference

    Following is a reference of File System module available in Node.js. For a further detail you can refer to official documentation.

    SNMethod & Description
    1fs.rename(oldPath, newPath, callback)
    Asynchronous rename(). No arguments other than a possible exception are given to the completion callback.
    2fs.ftruncate(fd, len, callback)
    Asynchronous ftruncate(). No arguments other than a possible exception are given to the completion callback.
    3fs.ftruncateSync(fd, len)
    Synchronous ftruncate()
    4fs.truncate(path, len, callback)
    Asynchronous truncate(). No arguments other than a possible exception are given to the completion callback.
    5fs.truncateSync(path, len)
    Synchronous truncate()
    6fs.chown(path, uid, gid, callback)
    Asynchronous chown(). No arguments other than a possible exception are given to the completion callback.
    7fs.chownSync(path, uid, gid)
    Synchronous chown()
    8fs.fchown(fd, uid, gid, callback)
    Asynchronous fchown(). No arguments other than a possible exception are given to the completion callback.
    9fs.fchownSync(fd, uid, gid)
    Synchronous fchown()
    10fs.lchown(path, uid, gid, callback)
    Asynchronous lchown(). No arguments other than a possible exception are given to the completion callback.
    11fs.lchownSync(path, uid, gid)
    Synchronous lchown()
    12fs.chmod(path, mode, callback)
    Asynchronous chmod(). No arguments other than a possible exception are given to the completion callback.
    13fs.chmodSync(path, mode)
    Synchronous chmod().
    14fs.fchmod(fd, mode, callback)
    Asynchronous fchmod(). No arguments other than a possible exception are given to the completion callback.
    15fs.fchmodSync(fd, mode)
    Synchronous fchmod().
    16fs.lchmod(path, mode, callback)
    Asynchronous lchmod(). No arguments other than a possible exception are given to the completion callback.Only available on Mac OS X.
    17fs.lchmodSync(path, mode)
    Synchronous lchmod().
    18fs.stat(path, callback)
    Asynchronous stat(). The callback gets two arguments (err, stats) where stats is a fs.Stats object.
    19fs.lstat(path, callback)
    Asynchronous lstat(). The callback gets two arguments (err, stats) where stats is a fs.Stats object. lstat() is identical to stat(), except that if path is a symbolic link, then the link itself is stat-ed, not the file that it refers to.
    20fs.fstat(fd, callback)
    Asynchronous fstat(). The callback gets two arguments (err, stats) where stats is a fs.Stats object. fstat() is identical to stat(), except that the file to be stat-ed is specified by the file descriptor fd.
    21fs.statSync(path)
    Synchronous stat(). Returns an instance of fs.Stats.
    22fs.lstatSync(path)
    Synchronous lstat(). Returns an instance of fs.Stats.
    23fs.fstatSync(fd)
    Synchronous fstat(). Returns an instance of fs.Stats.
    24fs.link(srcpath, dstpath, callback)
    Asynchronous link(). No arguments other than a possible exception are given to the completion callback.
    25fs.linkSync(srcpath, dstpath)
    Synchronous link().
    26fs.symlink(srcpath, dstpath[, type], callback)
    Asynchronous symlink(). No arguments other than a possible exception are given to the completion callback. The type argument can be set to 'dir', 'file', or 'junction' (default is 'file') and is only available on Windows (ignored on other platforms). Note that Windows junction points require the destination path to be absolute. When using 'junction', the destination argument will automatically be normalized to absolute path.
    27fs.symlinkSync(srcpath, dstpath[, type])
    Synchronous symlink().
    28fs.readlink(path, callback)
    Asynchronous readlink(). The callback gets two arguments (err, linkString).
    29fs.realpath(path[, cache], callback)
    Asynchronous realpath(). The callback gets two arguments (err, resolvedPath). May use process.cwd to resolve relative paths. cache is an object literal of mapped paths that can be used to force a specific path resolution or avoid additional fs.stat calls for known real paths.
    30fs.realpathSync(path[, cache])
    Synchronous realpath(). Returns the resolved path.
    31fs.unlink(path, callback)
    Asynchronous unlink(). No arguments other than a possible exception are given to the completion callback.
    32fs.unlinkSync(path)
    Synchronous unlink().
    33fs.rmdir(path, callback)
    Asynchronous rmdir(). No arguments other than a possible exception are given to the completion callback.
    34fs.rmdirSync(path)
    Synchronous rmdir().
    35fs.mkdir(path[, mode], callback)
    SAsynchronous mkdir(2). No arguments other than a possible exception are given to the completion callback. mode defaults to 0777.
    36fs.mkdirSync(path[, mode])
    Synchronous mkdir().
    37fs.readdir(path, callback)
    Asynchronous readdir(3). Reads the contents of a directory. The callback gets two arguments (err, files) where files is an array of the names of the files in the directory excluding '.' and '..'.
    38fs.readdirSync(path)
    Synchronous readdir(). Returns an array of filenames excluding '.' and '..'.
    39fs.close(fd, callback)
    Asynchronous close(). No arguments other than a possible exception are given to the completion callback.
    40fs.closeSync(fd)
    Synchronous close().
    41fs.open(path, flags[, mode], callback)
    Asynchronous file open.
    42fs.openSync(path, flags[, mode])
    Synchronous version of fs.open().
    43fs.utimes(path, atime, mtime, callback)
     
    44fs.utimesSync(path, atime, mtime)
    Change file timestamps of the file referenced by the supplied path.
    45fs.futimes(fd, atime, mtime, callback)
     
    46fs.futimesSync(fd, atime, mtime)
    Change the file timestamps of a file referenced by the supplied file descriptor.
    47fs.fsync(fd, callback)
    Asynchronous fsync. No arguments other than a possible exception are given to the completion callback.
    48fs.fsyncSync(fd)
    Synchronous fsync.
    49fs.write(fd, buffer, offset, length[, position], callback)
    Write buffer to the file specified by fd.
    50fs.write(fd, data[, position[, encoding]], callback)
    Write data to the file specified by fd. If data is not a Buffer instance then the value will be coerced to a string.
    51fs.writeSync(fd, buffer, offset, length[, position])
    Synchronous versions of fs.write(). Returns the number of bytes written.
    52fs.writeSync(fd, data[, position[, encoding]])
    Synchronous versions of fs.write(). Returns the number of bytes written.
    53fs.read(fd, buffer, offset, length, position, callback)
    Read data from the file specified by fd.
    54fs.readSync(fd, buffer, offset, length, position)
    Synchronous version of fs.read. Returns the number of bytesRead.
    55fs.readFile(filename[, options], callback)
    Asynchronously reads the entire contents of a file.
    56fs.readFileSync(filename[, options])
    Synchronous version of fs.readFile. Returns the contents of the filename.
    57fs.writeFile(filename, data[, options], callback)
    Asynchronously writes data to a file, replacing the file if it already exists. data can be a string or a buffer.
    58fs.writeFileSync(filename, data[, options])
    The synchronous version of fs.writeFile.
    59fs.appendFile(filename, data[, options], callback)
    Asynchronously append data to a file, creating the file if it not yet exists. data can be a string or a buffer.
    60fs.appendFileSync(filename, data[, options])
    The synchronous version of fs.appendFile.
    61fs.watchFile(filename[, options], listener)
    Watch for changes on filename. The callback listener will be called each time the file is accessed.
    62fs.unwatchFile(filename[, listener])
    Stop watching for changes on filename. If listener is specified, only that particular listener is removed. Otherwise, all listeners are removed and you have effectively stopped watching filename.
    63fs.watch(filename[, options][, listener])
    Watch for changes on filename, where filename is either a file or a directory. The returned object is a fs.FSWatcher.
    64fs.exists(path, callback)
    Test whether or not the given path exists by checking with the file system. Then call the callback argument with either true or false.
    65fs.existsSync(path)
    Synchronous version of fs.exists.
    66fs.access(path[, mode], callback)
    Tests a user's permissions for the file specified by path. mode is an optional integer that specifies the accessibility checks to be performed.
    67fs.accessSync(path[, mode])
    Synchronous version of fs.access. This throws if any accessibility checks fail, and does nothing otherwise.
    68fs.createReadStream(path[, options])
    Returns a new ReadStream object.
    69fs.createWriteStream(path[, options])
    Returns a new WriteStream object.
    70fs.symlink(srcpath, dstpath[, type], callback)
    Asynchronous symlink(). No arguments other than a possible exception are given to the completion callback. The type argument can be set to 'dir', 'file', or 'junction' (default is 'file') and is only available on Windows (ignored on other platforms). Note that Windows junction points require the destination path to be absolute. When using 'junction', the destination argument will automatically be normalized to absolute path.

  • GLOBAL OBJECTS ↓

    Global Objects


    Node.js global objects are global in nature and they are available in all modules. We do not need to include these objects in our application, rather we can use them directly. These objects are modules, functions, strings and object itself as explained below.

    __filename

    The __filename represents the filename of the code being executed. This is the resolved absolute path of this code file. For a main program this is not necessarily the same filename used in the command line. The value inside a module is the path to that module file.

    Example

    Create a js file named main.js which has the following code:

    // Let's try to print the value of __filename
    
    console.log( __filename );
    

    Now run the main.js to see the result:

    $ node main.js
    

    Based on the location of your program, it will print main file name as follows:

    /web/com/1427091028_21099/main.js
    

    __dirname

    The __dirname represents the name of the directory that the currently executing script resides in.

    Example

    Create a js file named main.js which has the following code:

    // Let's try to print the value of __dirname
    
    console.log( __dirname );
    

    Now run the main.js to see the result:

    $ node main.js
    

    Based on the location of your program, it will print current directory name as follows:

    /web/com/1427091028_21099
    

    setTimeout(cb, ms)

    The setTimeout(cb, ms) global function is used to run callback cb after at least ms milliseconds. The actual delay depends on external factors like OS timer granularity and system load. A timer cannot span more than 24.8 days.

    This function returns an opaque value that represents the timer which can be used to clear the timer.

    Example

    Create a js file named main.js which has the following code:

    function printHello(){
       console.log( "Hello, World!");
    }
    // Now call above function after 2 seconds
    setTimeout(printHello, 2000);
    

    Now run the main.js to see the result:

    $ node main.js
    

    Verify the output is printed after a little delay

    Hello, World!
    

    clearTimeout(t)

    The clearTimeout( t ) global function is used to stop a timer that was previously created with setTimeout(). Here t is the timer returned by setTimeout() function.

    Example

    Create a js file named main.js which has the following code:

    function printHello(){
       console.log( "Hello, World!");
    }
    // Now call above function after 2 seconds
    var t = setTimeout(printHello, 2000);
    
    // Now clear the timer
    clearTimeout(t);
    

    Now run the main.js to see the result:

    $ node main.js
    

    Verify the output where you will not find anything printed.

    setInterval(cb, ms)

    The setInterval(cb, ms) global function is used to run callback cb repeatedly after at least ms milliseconds. The actual delay depends on external factors like OS timer granularity and system load. A timer cannot span more than 24.8 days.

    This function returns an opaque value that represents the timer which can be used to clear the timer using the function clearInterval(t).

    Example

    Create a js file named main.js which has the following code:

    function printHello(){
       console.log( "Hello, World!");
    }
    // Now call above function after 2 seconds
    setInterval(printHello, 2000);
    

    Now run the main.js to see the result:

    $ node main.js
    

    Above program will execute function printHello() after every 2 second. Due to system limitation, this program can not be executed with Try it option so you can check it at your machine locally.

    Global Objects

    Following table gives a detail of few another objects which we use frequently in our applications. For a further detail you can refer to the official documentation.

    S.N.Module Name & Description
    1Console
    Used to print information on stdout and stderr.
    2Process
    Used to get information on current process. Provides multiple events related to process activities.

  • UTILITY MODULES ↓

    Utility Modules


    There are number of utility modules available in Node.js module library. These modules are very common and are frequently used while developing any Node based applications.

    S.N.Module Name & Description
    1OS Module
    Provides basic operating-system related utility functions.
    2Path Module
    Provides utilities for handling and transforming file paths.
    3Net Module
    Provides both servers and clients as streams. Acts as a network wrapper.
    4DNS Module
    Provides functions to do actual DNS lookup as well as to use underlying operating system name resolution functionalities.
    5Domain Module
    Provides way to handle multiple different I/O operations as a single group.

  • WEB MODULE ↓

    Web Module


    What is Web Server?

    Web Server is a software application which handles HTTP requests sent by the HTTP client, like web browsers, and returns web pages in response to the clients. Web servers usually delivers html documents along with images, style sheets and scripts.

    Most of the web server support server side scripts using scripting language or redirect to application server which perform the specific task of getting data from database, perform complex logic etc. and then sends a result to the HTTP client through the Web server.

    Apache web server is one of the most commonly used web server. It is an open source project.

    Web Application Architecture

    A Web application is usually divided into four layers:

    Web Architecture
    • Client - This layer consists of web browsers, mobile browsers or applications which can make HTTP request to the web server.

    • Server - This layer consists of Web server which can intercepts the request made by clients and pass them the response.

    • Business - This layer consists of application server which is utilized by web server to do required processing. This layer interacts with data layer via data base or some external programs.

    • Data - This layer consists of databases or any source of data.

    Creating Web Server using Node

    Node.js provides http module which can be used to create either HTTP client of server. Following is a bare minimum structure of HTTP server which listens at 8081 port.

    Create a js file named server.js:

    File: server.js

    var http = require('http');
    var fs = require('fs');
    var url = require('url');
    
    
    // Create a server
    http.createServer( function (request, response) {  
       // Parse the request containing file name
       var pathname = url.parse(request.url).pathname;
       
       // Print the name of the file for which request is made.
       console.log("Request for " + pathname + " received.");
       
       // Read the requested file content from file system
       fs.readFile(pathname.substr(1), function (err, data) {
          if (err) {
             console.log(err);
             // HTTP Status: 404 : NOT FOUND
             // Content Type: text/plain
             response.writeHead(404, {'Content-Type': 'text/html'});
          }else{	
             //Page found	  
             // HTTP Status: 200 : OK
             // Content Type: text/plain
             response.writeHead(200, {'Content-Type': 'text/html'});	
             
             // Write the content of the file to response body
             response.write(data.toString());		
          }
          // Send the response body 
          response.end();
       });   
    }).listen(8081);
    
    // Console will print the message
    console.log('Server running at http://127.0.0.1:8081/');
    

    Next let's create following html file named index.htm in the same directory where you created server.js

    File: index.htm

    <html>
    <head>
    <title>Sample Page</title>
    </head>
    <body>
    Hello World!
    </body>
    </html>
    

    Now let us run the server.js to see the result:

    $ node server.js
    

    Verify the Output

    Server running at http://127.0.0.1:8081/
    

    Make a request to Node.js server

    Open http://127.0.0.1:8081/index.htm in any browser and see the below result.

    First Server Application

    Verify the Output at server end.

    Server running at http://127.0.0.1:8081/
    Request for /index.htm received.
    

    Creating Web client using Node

    A web client can be created using http module. Let's check the following example.

    Create a js file named client.js:

    File: client.js

    var http = require('http');
    
    // Options to be used by request 
    var options = {
       host: 'localhost',
       port: '8081',
       path: '/index.htm'  
    };
    
    // Callback function is used to deal with response
    var callback = function(response){
       // Continuously update stream with data
       var body = '';
       response.on('data', function(data) {
          body += data;
       });
       
       response.on('end', function() {
          // Data received completely.
          console.log(body);
       });
    }
    // Make a request to the server
    var req = http.request(options, callback);
    req.end();
    

    Now run the client.js from a different command terminal other than server.js to see the result:

    $ node client.js
    

    Verify the Output.

    <html>
    <head>
    <title>Sample Page</title>
    </head>
    <body>
    Hello World!
    </body>
    </html>
    

    Verify the Output at server end.

    Server running at http://127.0.0.1:8081/
    Request for /index.htm received.
    

  • EXPRESS FRAMEWORK ↓

    Express Framework


    Express Overview

    Express is a minimal and flexible Node.js web application framework that provides a robust set of features to develop web and mobile applications. It facilitates a rapid development of Node based Web applications. Following are some of the core features of Express framework:

    • Allows to set up middlewares to respond to HTTP Requests.

    • Defines a routing table which is used to perform different action based on HTTP Method and URL.

    • Allows to dynamically render HTML Pages based on passing arguments to templates.

    Installing Express

    Firstly, install the Express framework globally using npm so that it can be used to create web application using node terminal.

    $ npm install express --save
    

    Above command saves installation locally in node_modules directory and creates a directory express inside node_modules. There are following important modules which you should install along with express:

    • body-parser - This is a node.js middleware for handling JSON, Raw, Text and URL encoded form data.

    • cookie-parser - Parse Cookie header and populate req.cookies with an object keyed by the cookie names.

    • multer - This is a node.js middleware for handling multipart/form-data.

    $ npm install body-parser --save
    $ npm install cookie-parser --save
    $ npm install multer --save
    

    Hello world Example

    Following is a very basic Express app which starts a server and listens on port 3000 for connection. This app responds with Hello World! for requests to the homepage. For every other path, it will respond with a 404 Not Found.

    var express = require('express');
    var app = express();
    
    app.get('/', function (req, res) {
       res.send('Hello World');
    })
    
    var server = app.listen(8081, function () {
    
      var host = server.address().address
      var port = server.address().port
    
      console.log("Example app listening at http://%s:%s", host, port)
    
    })
    

    Save the above code in a file named server.js and run it with the following command.

    $ node server.js
    

    You will see the following output:

    Example app listening at http://0.0.0.0:8081
    

    Open http://122.0.0.2:5031/ in any browser and see the below result.

    First Application

    Request & Response

    Express application makes use of a callback function whose parameters are request and response objects.

    app.get('/', function (req, res) {
       // --
    })
    

    You can check further detail on both the objects:

    • Request Object- The request object represents the HTTP request and has properties for the request query string, parameters, body, HTTP headers, and so on.

    • Response Object - The response object represents the HTTP response that an Express app sends when it gets an HTTP request.

    You can print req and res objects which provide lot of information related to HTTP request and response including cookies, sessions, URL etc.

    Basic Routing

    We have seen a basic application which serves HTTP request for the homepage. Routing refers to determining how an application responds to a client request to a particular endpoint, which is a URI (or path) and a specific HTTP request method (GET, POST, and so on).

    We will extend our Hello World program to add functionality to handle more type HTTP requests.

    var express = require('express');
    var app = express();
    
    // This responds with "Hello World" on the homepage
    app.get('/', function (req, res) {
       console.log("Got a GET request for the homepage");
       res.send('Hello GET');
    })
    
    
    // This responds a POST request for the homepage
    app.post('/', function (req, res) {
       console.log("Got a POST request for the homepage");
       res.send('Hello POST');
    })
    
    // This responds a DELETE request for the /del_user page.
    app.delete('/del_user', function (req, res) {
       console.log("Got a DELETE request for /del_user");
       res.send('Hello DELETE');
    })
    
    // This responds a GET request for the /list_user page.
    app.get('/list_user', function (req, res) {
       console.log("Got a GET request for /list_user");
       res.send('Page Listing');
    })
    
    // This responds a GET request for abcd, abxcd, ab123cd, and so on
    app.get('/ab*cd', function(req, res) {   
       console.log("Got a GET request for /ab*cd");
       res.send('Page Pattern Match');
    })
    
    
    var server = app.listen(8081, function () {
    
      var host = server.address().address
      var port = server.address().port
    
      console.log("Example app listening at http://%s:%s", host, port)
    
    })
    

    Save the above code in a file named server.js and run it with the following command.

    $ node server.js
    

    You will see the following output:

    Example app listening at http://0.0.0.0:8081
    

    Now you can try different requests at http://122.0.0.2:5031 to see the output generated by server.js. Following are few screens showing different responses for different URLs.

    Screen showing again http://122.0.0.2:5031/list_user

    Second Application

    Screen showing again http://122.0.0.2:5031/abcd

    Third Application

    Screen showing again http://122.0.0.2:5031/abcdefg

    Fourth Application

    Serving Static Files

    Express provides a built-in middleware express.static to serve static files, such as images, CSS, JavaScript etc.

    You simply needs to pass the name of the directory where you keep your static assets, to the express.static middleware to start serving the files directly. For example, if you keep your images, CSS, and JavaScript files in a directory named public, you can do this:

    app.use(express.static('public'));
    

    We will keep few images in public/images sub-directory as follows:

    node_modules
    server.js
    public/
    public/images
    public/images/logo.png
    

    Let's modify "Hello Word" app to add the functionality to handle static files.

    var express = require('express');
    var app = express();
    
    app.use(express.static('public'));
    
    app.get('/', function (req, res) {
       res.send('Hello World');
    })
    
    var server = app.listen(8081, function () {
    
      var host = server.address().address
      var port = server.address().port
    
      console.log("Example app listening at http://%s:%s", host, port)
    
    })
    

    Save the above code in a file named server.js and run it with the following command.

    $ node server.js
    

    Now open http://122.0.0.2:5031/images/logo.png in any browser and see the below result.

    Fifth Application

    GET Method

    Here is a simple example which passes two values using HTML FORM GET method. We are going to use process_get router inside server.js to handle this input.

    <html>
    <body>
    <form action="http://122.0.0.2:5031/process_get" method="GET">
    First Name: <input type="text" name="first_name">  <br>
    
    Last Name: <input type="text" name="last_name">
    <input type="submit" value="Submit">
    </form>
    </body>
    </html>
    

    Let's save above code in index.htm and modify server.js to handle home page request as well as input sent by the HTML form.

    var express = require('express');
    var app = express();
    
    app.use(express.static('public'));
    
    app.get('/index.htm', function (req, res) {
       res.sendFile( __dirname + "/" + "index.htm" );
    })
    
    app.get('/process_get', function (req, res) {
    
       // Prepare output in JSON format
       response = {
           first_name:req.query.first_name,
           last_name:req.query.last_name
       };
       console.log(response);
       res.end(JSON.stringify(response));
    })
    
    var server = app.listen(8081, function () {
    
      var host = server.address().address
      var port = server.address().port
    
      console.log("Example app listening at http://%s:%s", host, port)
    
    })
    

    Now accessing HTML document using http://122.0.0.2:5031/index.htm will generate following form:

    
    
    First Name:
    Last Name:

    Now you can enter First and Last Name and then click submit button to see the result and it should give result as follows:

    {"first_name":"John","last_name":"Paul"}
    

    POST Method

    Here is a simple example which passes two values using HTML FORM POST method. We are going to use process_get router inside server.js to handle this input.

    <html>
    <body>
    <form action="http://122.0.0.2:5031/process_post" method="POST">
    First Name: <input type="text" name="first_name">  <br>
    
    Last Name: <input type="text" name="last_name">
    <input type="submit" value="Submit">
    </form>
    </body>
    </html>
    

    Let's save above code in index.htm and modify server.js to handle home page request as well as input sent by the HTML form.

    var express = require('express');
    var app = express();
    var bodyParser = require('body-parser');
    
    // Create application/x-www-form-urlencoded parser
    var urlencodedParser = bodyParser.urlencoded({ extended: false })
    
    app.use(express.static('public'));
    
    app.get('/index.htm', function (req, res) {
       res.sendFile( __dirname + "/" + "index.htm" );
    })
    
    app.post('/process_post', urlencodedParser, function (req, res) {
    
       // Prepare output in JSON format
       response = {
           first_name:req.body.first_name,
           last_name:req.body.last_name
       };
       console.log(response);
       res.end(JSON.stringify(response));
    })
    
    var server = app.listen(8081, function () {
    
      var host = server.address().address
      var port = server.address().port
    
      console.log("Example app listening at http://%s:%s", host, port)
    
    })
    

    Now accessing HTML document using http://122.0.0.2:5031/index.htm will generate following form:

    
    
    First Name:
    Last Name:

    Now you can enter First and Last Name and then click submit button to see the result and it should give result as follows:

    {"first_name":"John","last_name":"Paul"}
    

    File Upload

    The following HTML code creates a file uploader form. This form is having method attribute set to POST and enctype attribute is set to multipart/form-data

    <html>
    <head>
    <title>File Uploading Form</title>
    </head>
    <body>
    <h3>File Upload:</h3>
    Select a file to upload: <br />
    <form action="http://122.0.0.2:5031/file_upload" method="POST" 
          enctype="multipart/form-data">
    <input type="file" name="file" size="50" />
    <br />
    <input type="submit" value="Upload File" />
    </form>
    </body>
    </html>
    

    Let's save above code in index.htm and modify server.js to handle home page request as well as file upload.

    var express = require('express');
    var app = express();
    var fs = require("fs");
    
    var bodyParser = require('body-parser');
    var multer  = require('multer');
    
    app.use(express.static('public'));
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(multer({ dest: '/tmp/'}));
    
    app.get('/index.htm', function (req, res) {
       res.sendFile( __dirname + "/" + "index.htm" );
    })
    
    app.post('/file_upload', function (req, res) {
    
       console.log(req.files.file.name);
       console.log(req.files.file.path);
       console.log(req.files.file.type);
    
       var file = __dirname + "/" + req.files.file.name;
       fs.readFile( req.files.file.path, function (err, data) {
            fs.writeFile(file, data, function (err) {
             if( err ){
                  console.log( err );
             }else{
                   response = {
                       message:'File uploaded successfully',
                       filename:req.files.file.name
                  };
              }
              console.log( response );
              res.end( JSON.stringify( response ) );
           });
       });
    })
    
    var server = app.listen(8081, function () {
    
      var host = server.address().address
      var port = server.address().port
    
      console.log("Example app listening at http://%s:%s", host, port)
    
    })
    

    Now accessing HTML document using http://122.0.0.2:5031/index.htm will generate following form:

    File Upload:
    Select a file to upload: 

    NOTE: This is just dummy form and would not work, but it must work at your server.

    Cookies Management

    You can send cookies to Node.js server which can handle the using the following middleware option. Following is a simple example to print all the cookies sent by the client.

    var express      = require('express')
    var cookieParser = require('cookie-parser')
    
    var app = express()
    app.use(cookieParser())
    
    app.get('/', function(req, res) {
      console.log("Cookies: ", req.cookies)
    })
    
    app.listen(8081)
    

  • RESTFUL API ↓

    RESTful API


    What is REST architecture?

    REST stands for REpresentational State Transfer. REST is web standards based architecture and uses HTTP Protocol. It revolves around resource where every component is a resource and a resource is accessed by a common interface using HTTP standard methods. REST was first introduced by Roy Fielding in 2000.

    A REST Server simply provides access to resources and REST client accesses and modifies the resources using HTTP protocol. Here each resource is identified by URIs/ global IDs. REST uses various representation to represent a resource like text, JSON, XML but JSON is the most popular one.

    HTTP methods

    Following four HTTP methods are commonly used in REST based architecture.

    • GET - This is used to provide a read only access to a resource.

    • PUT - This is used to create a new resource.

    • DELETE - This is used to remove a resource.

    • POST - This is used to update a existing resource or create a new resource.

    RESTful Web Services

    A web service is a collection of open protocols and standards used for exchanging data between applications or systems. Software applications written in various programming languages and running on various platforms can use web services to exchange data over computer networks like the Internet in a manner similar to inter-process communication on a single computer. This interoperability (e.g., communication between Java and Python, or Windows and Linux applications) is due to the use of open standards.

    Web services based on REST Architecture are known as RESTful web services. These webservices uses HTTP methods to implement the concept of REST architecture. A RESTful web service usually defines a URI, Uniform Resource Identifier a service, which provides resource representation such as JSON and set of HTTP Methods.

    Creating RESTful for A Library

    Consider we have a JSON based database of users having the following users in a file users.json:

    {
       "user1" : {
          "name" : "mahesh",
    	  "password" : "password1",
    	  "profession" : "teacher",
    	  "id": 1
       },
       "user2" : {
          "name" : "suresh",
    	  "password" : "password2",
    	  "profession" : "librarian",
    	  "id": 2
       },
       "user3" : {
          "name" : "ramesh",
    	  "password" : "password3",
    	  "profession" : "clerk",
    	  "id": 3
       }
    }
    

    Based on this information we are going to provide following RESTful APIs.

    S. N.URIHTTP MethodPOST bodyResult
    1listUsersGETemptyShow list of all the users.
    2addUserPOSTJSON StringAdd details of new user.
    3deleteUserDELETEJSON StringDelete an existing user.
    4:idGETemptyShow details of a user.

    I'm keeping most of the part of all the examples in the form of hard coding assuming you already know how to pass values from front end using Ajax or simple form data and how to process them using express Request object.

    List Users

    Let's implement our first RESTful API listUsers using the following code in a server.js file:

    var express = require('express');
    var app = express();
    var fs = require("fs");
    
    app.get('/listUsers', function (req, res) {
       fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
           console.log( data );
           res.end( data );
       });
    })
    
    var server = app.listen(8081, function () {
    
      var host = server.address().address
      var port = server.address().port
    
      console.log("Example app listening at http://%s:%s", host, port)
    
    })
    

    Now try to access defined API using http://122.0.0.2:5031/listUsers on local machine. This should produce following result:

    You can change given IP address when you will put the solution in production environment.

    {
       "user1" : {
          "name" : "mahesh",
          "password" : "password1",
          "profession" : "teacher",
          "id": 1
       },
       "user2" : {
          "name" : "suresh",
          "password" : "password2",
          "profession" : "librarian",
          "id": 2
       },
       "user3" : {
          "name" : "ramesh",
          "password" : "password3",
          "profession" : "clerk",
          "id": 3
       }
    }
    

    Add User

    Following API will show you how to add new user in the list. Following is the detail of the new user:

    user = {
       "user4" : {
          "name" : "mohit",
          "password" : "password4",
          "profession" : "teacher",
          "id": 4
       }
    }
    

    You can accept the same input in the form of JSON using Ajax call but for teaching point of view, we are making it hard coded here. Following is the addUser API to a new user in the database:

    var express = require('express');
    var app = express();
    var fs = require("fs");
    
    var user = {
       "user4" : {
          "name" : "mohit",
          "password" : "password4",
          "profession" : "teacher",
          "id": 4
       }
    }
    
    app.get('/addUser', function (req, res) {
       // First read existing users.
       fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
           data = JSON.parse( data );
           data["user4"] = user["user4"];
           console.log( data );
           res.end( JSON.stringify(data));
       });
    })
    
    var server = app.listen(8081, function () {
    
      var host = server.address().address
      var port = server.address().port
      console.log("Example app listening at http://%s:%s", host, port)
    
    })
    

    Now try to access defined API using http://122.0.0.2:5031/addUsers on local machine. This should produce following result:

    { user1:
       { name: 'mahesh',
         password: 'password1',
         profession: 'teacher',
         id: 1 },
      user2:
       { name: 'suresh',
         password: 'password2',
         profession: 'librarian',
         id: 2 },
      user3:
       { name: 'ramesh',
         password: 'password3',
         profession: 'clerk',
         id: 3 },
      user4:
       { name: 'mohit',
         password: 'password4',
         profession: 'teacher',
         id: 4 } 
    }
    

    Show Detail

    Now we will implement an API which will be called using user ID and it will display the detail of the corresponding user.

    var express = require('express');
    var app = express();
    var fs = require("fs");
    
    app.get('/:id', function (req, res) {
       // First read existing users.
       fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
           data = JSON.parse( data );
           var user = users["user" + req.params.id] 
           console.log( user );
           res.end( JSON.stringify(user));
       });
    })
    
    var server = app.listen(8081, function () {
    
      var host = server.address().address
      var port = server.address().port
      console.log("Example app listening at http://%s:%s", host, port)
    
    })
    

    Now let's call above service using http://122.0.0.2:5031/2 on local machine. This should produce following result:

    {
       "name":"suresh",
       "password":"password2",
       "profession":"librarian",
       "id":2
    }
    

    Delete User

    This API is very similar to addUser API where we receive input data through req.body and then based on user ID we delete that user from the database. To keep our program simple we assume we are going to delete user with ID 2.

    var express = require('express');
    var app = express();
    var fs = require("fs");
    
    var id = 2;
    
    app.get('/deleteUser', function (req, res) {
    
       // First read existing users.
       fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
           data = JSON.parse( data );
           delete data["user" + 2];
           
           console.log( data );
           res.end( JSON.stringify(data));
       });
    })
    
    var server = app.listen(8081, function () {
    
      var host = server.address().address
      var port = server.address().port
      console.log("Example app listening at http://%s:%s", host, port)
    
    })
    

    Now let's call above service using http://122.0.0.2:5031/deleteUser on local machine. This should produce following result:

    { user1:
       { name: 'mahesh',
         password: 'password1',
         profession: 'teacher',
         id: 1 },
      user3:
       { name: 'ramesh',
         password: 'password3',
         profession: 'clerk',
         id: 3 } 
    }
    

  • SCALING APPLICATION ↓

    Scaling Application


    As Node.js runs in a single thread mode but it uses an event-driven paradigm to handle concurrency. It also facilitates creation of child processes to leverage parallel processing on multi-core cpu based systems.

    Child processes always have three streams child.stdin, child.stdout, and child.stderr which may be shared with the stdio streams of the parent process.

    Node provides child_process module which has following three major ways to create child process.

    • exec - child_process.exec method runs a command in a shell/console and buffers the output.

    • spawn - child_process.spawn launches a new process with a given command

    • fork - The child_process.fork method is a special case of the spawn() to create child processes.

    The exec() method

    child_process.exec method runs a command in a shell and buffers the output. It has the following signature:

    child_process.exec(command[, options], callback)
    

    Parameters

    Here is the description of the parameters used:

    • command String The command to run, with space-separated arguments

    • options Object may comprise one or more of the following options:

      • cwd String Current working directory of the child process

      • env Object Environment key-value pairs

      • encoding String (Default: 'utf8')

      • shell String Shell to execute the command with (Default: '/bin/sh' on UNIX, 'cmd.exe' on Windows, The shell should understand the -c switch on UNIX or /s /c on Windows. On Windows, command line parsing should be compatible with cmd.exe.)

      • timeout Number (Default: 0)

      • maxBuffer Number (Default: 200*1024)

      • killSignal String (Default: 'SIGTERM')

      • uid Number Sets the user identity of the process.

      • gid Number Sets the group identity of the process.

    • callback Function gets three arguments error, stdout and stderr which is called with the following output when process terminates

    The exec() method returns a buffer with a max size and waits for the process to end and tries to return all the buffered data at once.

    Example

    Let us create two js file named support.js and master.js:

    File: support.js

    console.log("Child Process " + process.argv[2] + " executed." );
    

    File: master.js

    const fs = require('fs');
    const child_process = require('child_process');
    
    for(var i=0; i<3; i++) {
       var workerProcess = child_process.exec('node support.js '+i,
          function (error, stdout, stderr) {
             if (error) {
                console.log(error.stack);
                console.log('Error code: '+error.code);
                console.log('Signal received: '+error.signal);
             }
             console.log('stdout: ' + stdout);
             console.log('stderr: ' + stderr);
          });
    
          workerProcess.on('exit', function (code) {
          console.log('Child process exited with exit code '+code);
       });
    }
    

    Now run the master.js to see the result:

    $ node master.js
    

    Verify the Output. Server has started

    Child process exited with exit code 0
    stdout: Child Process 1 executed.
    
    stderr:
    Child process exited with exit code 0
    stdout: Child Process 0 executed.
    
    stderr:
    Child process exited with exit code 0
    stdout: Child Process 2 executed.
    

    The spawn() method

    child_process.spawn method launches a new process with a given command. It has the following signature:

    child_process.spawn(command[, args][, options])
    

    Parameters

    Here is the description of the parameters used:

    • command String The command to run

    • args Array List of string arguments

    • options Object may comprise one or more of the following options:

      • cwd String Current working directory of the child process

      • env Object Environment key-value pairs

      • stdio Array|String Child's stdio configuration

      • customFds Array Deprecated File descriptors for the child to use for stdio

      • detached Boolean The child will be a process group leader

      • uid Number Sets the user identity of the process.

      • gid Number Sets the group identity of the process.

    The spawn() method returns streams (stdout & stderr) and it should be used when the process returns large amount of data. spawn() starts receiving the response as soon as the process starts executing.

    Example

    Create two js file named support.js and master.js:

    File: support.js

    console.log("Child Process " + process.argv[2] + " executed." );
    

    File: master.js

    const fs = require('fs');
    const child_process = require('child_process');
     
    for(var i=0; i<3; i++) {
       var workerProcess = child_process.spawn('node', ['support.js', i]);
    
       workerProcess.stdout.on('data', function (data) {
          console.log('stdout: ' + data);
       });
    
       workerProcess.stderr.on('data', function (data) {
          console.log('stderr: ' + data);
       });
    
       workerProcess.on('close', function (code) {
          console.log('child process exited with code ' + code);
       });
    }
    

    Now run the master.js to see the result:

    $ node master.js
    

    Verify the Output. Server has started

    stdout: Child Process 0 executed.
    
    child process exited with code 0
    stdout: Child Process 1 executed.
    
    stdout: Child Process 2 executed.
    
    child process exited with code 0
    child process exited with code 0
    

    The fork method

    child_process.fork method is a special case of the spawn() to create Node processes. It has the following signature

    child_process.fork(modulePath[, args][, options])
    

    Parameters

    Here is the description of the parameters used:

    • modulePath String The module to run in the child

    • args Array List of string arguments

    • options Object may comprise one or more of the following options:

      • cwd String Current working directory of the child process

      • env Object Environment key-value pairs

      • execPath String Executable used to create the child process

      • execArgv Array List of string arguments passed to the executable (Default: process.execArgv)

      • silent Boolean If true, stdin, stdout, and stderr of the child will be piped to the parent, otherwise they will be inherited from the parent, see the "pipe" and "inherit" options for spawn()'s stdio for more details (default is false)

      • uid Number Sets the user identity of the process.

      • gid Number Sets the group identity of the process.

    The fork method returns object with a built-in communication channel in addition to having all the methods in a normal ChildProcess instance.

    Example

    Create two js file named support.js and master.js:

    File: support.js

    console.log("Child Process " + process.argv[2] + " executed." );
    

    File: master.js

    const fs = require('fs');
    const child_process = require('child_process');
     
    for(var i=0; i<3; i++) {
       var worker_process = child_process.fork("support.js", [i]);	
    
       worker_process.on('close', function (code) {
          console.log('child process exited with code ' + code);
       });
    }
    

    Now run the master.js to see the result:

    $ node master.js
    

    Verify the Output. Server has started

    Child Process 0 executed.
    Child Process 1 executed.
    Child Process 2 executed.
    child process exited with code 0
    child process exited with code 0
    child process exited with code 0
    

  • PACKAGING ↓

    Packaging


    Node.js code is open and ready to be copied like any other Javascript code. But now its not possible anymore. JXcore which is an open source project, introduces a unique feature for packaging and encryption of source files and other assets into JX packages.

    Consider you have a large project consisting of many files. JXcore is very much able to pack them all into a single file to simplify the distribution. This tutorial will give you a quick overview about the whole process starting from installing JXcore.

    JXcore Installation

    Installing a JXcore is as simple as just download and unpack the package which provide jx binary to start with. So let's follow the following steps:

    Step 1

    Download JXcore package from the http://jxcore.com/downloads/, as per your operating system and machine architecture. We downloaded a package for Cenots running on 64 bit machine.

    $ wget https://s3.amazonaws.com/nodejx/jx_rh64.zip
    

    Step 2

    Unpack the downloaded file jx_rh64.zip and copy jx binary into /usr/bin or may be in any other directory based on your system setup.

    $ unzip jx_rh64.zip
    $ cp jx_rh64/jx /usr/bin
    

    Step 3

    Finally set your PATH variable appropriately to run jx from anywhere you like.

    $ export PATH=$PATH:/usr/bin
    

    Step 4

    You can verify your installation by issuing a simple command. If everything is fine then you will find it working and printing its version number as follows:

    $ jx --version
    v0.10.32
    

    Packaging Code

    Consider you have following a project with the following directories where you kept your all the files including Node.js main file index.js and all the modules installed locally.

    drwxr-xr-x  2 root root  4096 Nov 13 12:42 images
    -rwxr-xr-x  1 root root 30457 Mar  6 12:19 index.htm
    -rwxr-xr-x  1 root root 30452 Mar  1 12:54 index.js
    drwxr-xr-x 23 root root  4096 Jan 15 03:48 node_modules
    drwxr-xr-x  2 root root  4096 Mar 21 06:10 scripts
    drwxr-xr-x  2 root root  4096 Feb 15 11:56 style
    

    To package the above project, you simply need to go inside this directory and issue the following jx command, assuming index.js is the entry file for your Node.js project:

    $ jx package index.js index
    

    Here you could have used any other package name instead of index, I used it because I want keep my main file name as index.jx. However, above command will pack everything and will create following two files:

    • index.jxp This is an intermediate file whcih contains complete project detail needed to compile the project.

    • index.jx This is the binary file having complete package and ready to be shipped to your client or in your production environment.

    Launching JX File

    Consider your orignal Node.js project was running as follows:

    $ node index.js command_line_arguments
    

    Now after compiling your package using JXcore, it can be started as follows:

    $ jx index.jx command_line_arguments
    

    For a further detail on JXcore, you can check its official website.