When building Node.js applications, perhaps the most important concept to understand, and often misunderstood, is its concurrency model for handling I/O operations and the use of callback functions. Node.js is an event-driven, non-blocking, single-threaded JavaScript runtime environment built on Chrome’s V8 engine which allows it to execute JavaScript code on the server-side. In Node’s architecture, this event-driven model is provided by a mechanism called the event loop. The event loop is what allows Node.js to handle high throughput operations and it is supplemented by a multi-platform C library called libuv(https://github.com/libuv/libuv). When talking about I/O operations in Node.js, it usually refers to slow operations such as accessing external resources such as disks or network resources. These types of I/O operations are the most time-expensive as they take longer time to complete. And waiting for I/O to complete is the largest waste in most programming languages.Node’s event loop was designed around this idea that waiting for I/O operations to complete is the most time-expensive in computer programming. It is designed to scale well and handle hundreds or thousands of connections without breaking a sweat. Asynchronicity is not an afterthought, but it’s baked right in the design of Node.js.## Handling I/O BasicsThere are three popular ways to deal with slow I/O operations. The easiest way is to process requests **synchronously**, that is, handle one request at a time. But this is a bad approach because it will hold up other requests. No other request will be processed until the current request is completed. Another approach is to **fork a new process** to handle each new request. While this is an improvement over the first approach, this does not scale well for hundreds or thousands of requests. Forking a new process is memory-expensive since resources will be allocated to each new process even when idle.The most popular approach to handling I/O requests is *threads*, In this approach, a new thread is created to handle each new request. While this approach uses less memory and resources, things can get complicated easily since you have to deal with managing shared resources.An example of a multithreaded approach is the Apache web server. Apache is multithreaded, it spawns a new thread for every new request. If you have used Apache before, you can see how it consumes memory as the number of concurrent connection increases and more threads are created to handle new requests. On the other hand, Nginx, a popular alternative to Apache is single threaded. It doesn’t have a high memory usage even when it handles a large number of concurrent requests.Nginx, similar to Node.js, is single-threaded but event-driven and it also utilizes an event loop to handle multiple requests in a single thread. The event loop is used to handle requests for slow I/O operations without blocking the main thread of execution. ## The Event LoopThe event loop is the mechanism that allows Node.js to perform non-blocking I/O operations, by offloading I/O operations to the OS (operating system) kernel whenever possible. Despite being single-threaded, Node.js takes advantage of the kernel being multithreaded which can handle multiple operations in the background.The event loop starts automatically whenever Node.js executes your JavaScript code. This is what makes the asynchronous style of programming possible in Node.js. It is a semi-infinite loop that performs polling and blocking calls to the system kernel until one of the operations is completed. When an operation is completed, the kernel will notify Node.js that the appropriate callback function may be added to its poll queue to be eventually executed. Node.js exits when it no longer has any events to process. At this point, the event loop must complete and exit.  Contrary to popular event loop diagrams found on the web, the event loop in Node.js does not run through and process a stack. The event loop goes through a set of *phases* with specific tasks that are handled in a round-robin fashion. Another common misconception is that asynchronous operations in Node are always loaded off to the thread pool provided by libuv. The truth is, it only uses the thread pool provided by libuv for asynchronous I/O only when there is no other way. As much as possible, the event loop will utilize first asynchronous interfaces available in the operating system before it uses its own.Libuv, by default, provides a pool of four threads. But these threads will only be used if the event loop has no other option. This default value can be overwridden to improve perfromance by setting a higher value to an environment variable called `UV_THREADPOOL_SIZE`.## Phases OverviewUnderstanding what occurs in each phase of the event loop is the key to fully understand the event loop. The following are the phases of each run of the event loop:* Timers – callbacks scheduled by `setTimeout()` and `setInterval()` will be processed in this phase*  I/O callbacks – this is where callbacks from the user code will be processed* Poll – this is the phase of retrieving new I/O events. Node.js will also block when necessary* Set Immediate – where `setImmediate()` callbacks are processed* Close – where all `on(close)` callbacks are handledA more detailed explanation of what happens in each phase can be found on the Node.js website(https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c).It’s also important to know that there’s a FIFO (first in first out) queue of callbacks for execution in each phase. When the event loop enters a phase, it will perform any operations specific to the current phase, until the queue has been exhausted or the maximum number of callbacks has been executed. When the queue of the current phase has been exhausted or reached the callback limit, the event loop will move to the next phase, and so on.## SummaryThis is just short overview of the Node.js’s event-driven concurrency model and how the event loop works. Despite being single-threaded, Node.js can handle I/O operations in a very efficient and scalable way because of its low resource requirement per connection.Understanding how the event loop works is an important concept to grasp so you’ll know how to improve the performance of your Node.js applications. It will also help you write efficient code that can handle asynchronous calls properly.## References- Everything You Need to Know About Node.js Event Loop(https://www.youtube.com/watch?v=PNa9OMajw9w)- Node’s Event Loop From the Inside Out(https://www.youtube.com/watch?v=P9csgxBgaZ8)- The Node.js Event Loop, Timers, and process.nextTick()(https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/)- What you should know to really understand the Node.js Event Loop(https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c)

x

Hi!
I'm Joan!

Would you like to get a custom essay? How about receiving a customized one?

Check it out