Introduction to Node.js Event Loop
In a traditional Input/Output, when a request comes to a web server, it is assigned to a specific thread. For each concurrent connection, there is a new thread and the thread will continue to run until a response is sent for a particular request. This is a perfect example of Blocking I/O (Input/Output network operation) because when handling a particular request by a thread there will be some idle time when between operations are being performed such as retrieving a file, opening it, reading it, etc.
Each of these thread consumes memory and thus, a thread which runs for a longer period of time and also sits ideally for a significant amount of time in between will definitely consume a lot of memory. This is one of the main reason that the core APIs in Node.js are built in non-blocking way and support asynchronous I/O.
Hence, we can say that Node.js is itself a runtime environment. It follows an observer pattern (also known as Reactor Pattern in other programming languages) which allows each incoming I/O request to be associated and handle within a function or a handler. This handler function is called a callback function.
At the time of running a Node.js environment, an Event Loop is initialized which handles the I/O operations by offloading them to an operating system’s kernel. The different operating system uses different kernels but their basic mechanism of handling an I/O is similar. These kernels are multi threaded and can handle execution of multiple operations in the background. Whenever an I/O operation completes, the Kernel notifies Node.js about it and callback handling that operation will complete its execution.
All of these operations are queued in a poll which is also known as Event Queue. Any of these operations may proceed to more operations and these new operations are then again added to the Event Queue. In summary, Event Loop will always be responsible for the execution of all the asynchronous callbacks registered for every event in the Event Queue. Other than I/O operations that are queued in the Event Queue or poll the other types of callbacks can also execute with the Event Loop. These other types are:
This timer function is used to schedule the callback associated after described period of time in milliseconds. The first argument to this function is always a callback which can also be declared separately. The second argument of the timer function is the number of milliseconds defined.
This timer function behaves differently and only executes the code associated at the end of an Event Loop cycle. This code will execute after every I/O operation in the current event loop and before any timers scheduled for the next event loop.
The above snippet of code will output as:
```shell before immediate after immediate executing immediately: during immediate ```
The first argument is again is the callback that associates the code to be deferred. Any other optional arguments can be passed to the function when it is executed like we have done above in our example. There is no need to define a time limit to defer the execution of this function since it will always run at the end of an Event Loop cycle in any Node.js program.
Now suppose, there is a callback that you want to execute in your Node.js module a multiple times. In that case, setInterval() can be used. It again takes a callback as the first argument and runs an infinite number of times. The delay between each iteration is defined in milliseconds. Otherwise, this timer function behave is written in a similar manner as of setTimeout().
To stop a setInterval() function from executing the infinite number of times, we can use another function that will perform stop its behavior, clearInterval().
Apart from all timer functions being global, there is another object that global and does need to be required in any Node.js module. It is called process. Discussing everything this object holds is vast discussion and is out of the scope of this article. However, we are interested in a particular method the API contains and it is called `process.nexTick()`.
```shell Processed in the first iteration Processed in next iteration ```
In Node.js events are associated with operations in Event Loop. For example, a TCP network server emits a _connect_ event every time a new client connects, or a stream can emit a _data_ event every time a new chunk of data is available to read. These objects in Node.js are called _event emitters_.
These objects that emit events are defined as the instances of the class events.EventEmitter. These objects reveal an eventEmitter.on() a function that allows one or more functions to be attached to named events emitted. When an EventEmitter object emits the event, the functions attached to that specific event are called synchronously.