Asynchrony is hard for any programming language. Asynchronous in Node.js is unpredictable and difficult to trace when there are some bugs. JavaScript is single-threaded. Utilizing multiple threads is most challenging because of its inherent complexity. Both Programmer and OS give a lot of effort to deliver a solution, But nodejs event loop is crazy.
It is a single-threaded asynchronous concurrent loop. A single thread can do one thing at a time. In the event loop, multiple requests can get queued at the same time and that makes it concurrent. Loop doesn’t wait for everything from one request for complete but callback comes without blocking anything.
It is a semi-finite type loop where if the queue is empty, the loop will automatically exit. Node.js uses libuv in the operating systems for callbacks for incoming connections.
It pounds bugs when different strings share assets since single-string circle cuts string security edge cases and would context be able to switch a lot quicker. It makes this circle a versatile and powerful utilization of associations.
Let’s see how it’s happened in real code —
Example the block of the main loop —
setTimeout(
() => console.log('Hyy, I'm from the callback queue'),
5000); // Loop will pause for 5s
const stopTime = Date.now() + 2000;
while (Date.now() < stopTime) {} // block of main code
At every iteration, the loop unwinds the call stack, then polls. On the off chance that you run this code, note the circle gets obstructed for two seconds. Be that as it may, the circle remains alive until the callback executes in five seconds. When the principle circle unblocks, the surveying system makes sense of how long it looks out for callbacks.
Callback Queue —
const stopTime = Date.now() + 2000;
while (Date.now() < stopTime) {} // Block the main loop
// This takes 7 secs to execute
setTimeout(() => console.log('Ran callback A'), 5000);
It’s a humble single-threaded loop, concurrent, and non-blocking.
The idea of wrapping synchronous I/O around async/await to avoid blocking the main loop.
const fs = require('fs');
const readFileSync = async (path) => await fs.readFileSync(path);
readFileSync('readme.md').then((data) => console.log(data));
console.log('The event loop continues without blocking...');
Where await comes from callback queue, the code read like synchronous blocking code but it never blocks. In the above code, fs.readFile fires a callback that can be wrapped around a promise.
The occasion circle keeps on emphasizing through each stage as callbacks get lined. Be that as it may, inside each stage there’s a method to line another sort of callback.
process.nextTick() versus setImmediate()
Toward the finish of each stage, the circle executes the process.nextTick() callback. Note that this callback type isn’t a piece of the occasion circle since it runs toward the finish of each stage. The setImmediate() callback is a piece of the general occasion circle, so it’s not as quick as the name infers. Since process.nextTick() needs close information on the occasion circle, I suggest utilizing setImmediate() when all is said in done.
Example of an event emitter in its own constructor. The call stack must unwind first before calling the event.
const EventEmitter = require('events');
class ImpatientEmitter extends EventEmitter {
constructor() {
super();
// Fire this at the end of the phase with an unwound call stack
process.nextTick(() => this.emit('event'));
}
}
const emitter = new ImpatientEmitter();
emitter.on('event', () => console.log('An impatient event occurred!'));
Permitting the call stack to loosen up can forestall mistakes like RangeError: Maximum call stack size surpassed.
One gotcha is to ensure process.nextTick() doesn’t obstruct the occasion circle. Blocking can be hazardous with recursive callback calls inside a similar stage.
Previously published at https://centocode.com/node-js-event-loop-is-an-awesome-concept-for-developers/