Signup/Sign In
LAST UPDATED: SEPTEMBER 22, 2021

What is Node.js?

    Node.js is a JavaScript runtime environment that is built on Chrome's V8 JavaScript engine. It is open-source and server-side. It is free and is based on the concept of asynchronous programming.

    Node.js is free from deadlocks and no function in Node.js directly performs any I/O operations due to which no process is blocked. Since there is no blocking of the processes it is easy to develop scalable systems in Node.js. It's single-threaded, deadlock-free and asynchronous nature makes it memory efficient. Node goes to sleep when there is no task to be performed.

    When a task is sent to the computer's file system other languages like PHP and ASP wait while the computer's file system opens and reads the file, which is not the case with Node.js it simply continues with the next request.

    Node.js can be used to develop different applications such as web application which generates dynamic content, in the file system to create, open, read, close, and delete files on the server, command-line application, REST API server, etc.


    Understanding Node.js Architecture

    Node.js is a single-threaded model with the Event Loop Model. It doesn't follow the Request/Response Multi-threaded Stateless Model.

    Node.js Architecture

    Source: Stackoverflow

    The architecture comprises of two main components: Core and Models. It is built in C & C++. It combines Google V8 JS engine with Node's Libuv library and protocol bindings including sockets & HTTP.


    Components in the Architecture

    • V8: It is an open-source JavaScript engine by Google, implemented in C++. The V8 converts the code you write in JavaScript into machine code.

    • libuv: It is a C++ library that provides asynchronous features. It maintains event-loop, a thread pool, file system, DNS functionalities, etc.

    • Other C/C++ Components/Dependencies: such as c-ares, crypto (OpenSSL), http-parser, and zlib. These dependencies provide low-level interactions with servers to establish important functionalities such as networking, encrypting, etc.

    • Application/Modules: This is the part where you write your code. It contains Node.js core modules and any modules that you write yourself.

    • Node.js Bindings: You know that Node.js is written in C/C++ and JavaScript. The reason for using C/C++ is that many code/libraries are simple and hence they are fast. So how can JavaScript communicate with the code written in C/C++? For this Node.js uses binding. Binding is a way by which code written in different languages can communicate with each other. So binding helps the C/C++ libraries like (c-ares, zlib, http-parser etc) to bind to JavaScript. Binding also helps in code-reusability and also improves the performance of the system as some languages like C/C++ are much faster than other high-level languages like Python, JavaScript, etc.


    Some Important Terminologies:

    • Non-blocking/Asynchronous: Whenever the request comes, the application would handle the request and block the other processes until the request is processed. Suppose if a large number of request comes to the application there would be a large number of waiting queue of processes i.e. it will block the process which come after the current process. Node.js handles the blocking/halted processes in a different way. In Node.js whenever a request comes, instead of giving the request to a new thread, all the requests are handled by the main thread. So whenever a request such as a file access, database read/write request comes, it is sent to the worker threads maintained by libuv. Thus the I/O operations are handled by the worker threads and not the main threads and so the main thread never gets blocked. You only get to work with the main thread while all other libuv's worker threads are hidden from you and are taken care of by Node.js.

    • Event-Driven: In most of the modern systems, the processes are initiated by the incoming request. When a request is made, a thread is created for that request and the operations are done sequentially, if any of the operation is found to be slow then all other subsequent operations automatically slows down, as execution is being done sequentially. When all the operations are complete then the response is returned. This is not the case with Node.js, in Node.js all the operations are registered to Node.js events, waiting to be triggered, either by the main application or requests.

    • Runtime: Node.js runtime helps in the execution of the Node.js applications.


    Understanding the Workflow

    Now that you are aware of the terminologies it will be easy for you to understand how different components in Node.js interact with each other.

    • The V8 engine runs the code of your Node.js application when it starts running. The objects in the application keep the list of observers. The observers are the function registered to events, which gets notified whenever the respective events get emitted.

    • Now, whenever the event gets emitted, its callback function gets enqueued into the event loop. The event loop will dequeue the events and put them onto the call stack. The new event will be put onto the call stack once the previous event is processed.

    • On the call stack whenever I/O operation is encountered, it will be handed over to libuv for processing. The worker threads will interact with Node.js's low-level libraries to perform operations such as database transactions, file access, etc. When the processing is over the libuv will enqueue the event back on the event queue for the main thread to work on. While the libuv handles asynchronous I/O operations, the main thread doesn't wait for the outcome but moves to the next process. The event returned by libuv will have the opportunity to be handled by the main thread again when it is put back onto the call stack by the event loop.


    Time for an Example

    Think of Node.js application as McDonald's restaurant.

    Customers come to the counter and give the order to a waiter(the main thread).

    When a large number of customers visit at the same time, they wait in a line (enqueued in the event queue) for their turn.

    Once the customer is served by the waiter, the waiter passes the order to the manager(libuv), who assigns the order to the other chef(worker threads).

    The chefs will use different ingredients and machines(low-level C/C++ components) depending upon the order.

    Once the waiter passes the order to the manager, he doesn't wait for the order to be prepared instead, the waiter takes the order of the next customer in the line(the dequeued event loop and pushed onto the call stack).

    The current event is the customer that is being served at the counter. When the order is ready the waiter calls the name of the customer and the customer gets his order.


    Advantages of Node.js

    1. It is open-source and free.

    2. Asynchronous: Node.js is asynchronous ie. non-blocking. It doesn't wait while the file system opens and reads the file instead it sends the task to the computer's file system and is ready to handle the next request. The asynchronous nature makes it fast.

    3. No Buffering: Node.js applications don't buffer data. Node.js applications output the data in chunks.

    4. Is Single-Threaded, Highly Scalable: It follows a single-threaded model with event looping. The server responds in a non-blocking way which makes Node.js based applications highly scalable as compared to traditional servers like Apache.

    5. It uses JavaScript to build a server-side application.
    6. It runs on various platforms such as Windows, MAC OS, Linux.

    You may also like:

    Working as an Application Developer. I love to learn and discover things JavaScript, HTML, and CSS.
    IF YOU LIKE IT, THEN SHARE IT
    Advertisement

    RELATED POSTS