takarajapaneseramen.com

Understanding Event-Driven Programming in Node.js

Written on

Chapter 1: Introduction to Event-Driven Architecture

Node.js operates on an asynchronous event-driven architecture, where its main APIs reactively handle events. In this structure, an emitter triggers a specific event, which then activates callback functions linked through listeners designated for that event.

To delve deeper into this programming model within a Node.js application, let’s analyze a practical example of reading a file:

const fs = require('fs');

const textStream = fs.createReadStream('data.txt', 'utf-8');

textStream.on('readable', () => {

console.log(textStream.read());

});

textStream.on('end', () => console.log('File Read Completed'));

Here, the textStream object, generated by fs.createReadStream, serves as an emitter that generates various named events as they occur. For instance, when the file data is ready to be read, a readable event is emitted. A listener callback function is linked to this event using the on method. When the readable event is triggered, the corresponding callback logs the file contents, demonstrating the asynchronous, event-driven nature of the code. When the file reading finishes, an end event is emitted, invoking its associated callback.

We can observe a consistent pattern: specific actions—whether from users or the system—emit events. Listeners subscribed to these events capture the emissions, and their callbacks dictate the response to each emitted event.

The first video titled "Understanding Event-Driven Architecture | Fundamentals of NODE JS" offers an overview of this foundational concept.

Chapter 2: Creating Custom Events

Custom events can be established in Node.js by instantiating the EventEmitter class:

const EventEmitter = require('events');

const customEvent = new EventEmitter();

We can then add a listener for our custom event:

customEvent.on('my_custom_event', (data) => {

console.table(data);

});

The on method of the customEvent object attaches listeners to specific events, which by default accumulate in the listener array. If we need a listener to execute before the others, we can utilize the prependListener method on the emitter object.

Subsection 2.1: Emitting Custom Events

We can emit our custom-named events as shown below:

customEvent.emit('my_custom_event', {

key1: 'val1',

key2: 'val2',

});

The emit method accepts the event name as its first argument, followed by any additional parameters:

emitter.emit(eventName, [...args]);

Another interesting feature is adding listeners that trigger only once when an event occurs. This is achievable through the once method:

customEvent.once('my_custom_event', (data) => {

console.table(data);

});

This configuration ensures the listener callback activates only on the first emission of the my_custom_event, disregarding subsequent emissions.

Chapter 3: Managing Workflow with Event-Driven Patterns

The event-driven model is also effective for orchestrating workflows, including managing error states through the emitter-listener paradigm. Consider a hypothetical delivery status check:

const checkDeliveryStatus = () => {

const induceSystemError = Boolean(Math.round(Math.random()));

const isDeliverySuccessful = Boolean(Math.round(Math.random()));

if (induceSystemError) {

const systemError = new Error(DELIVERY_STATES.ERRORED.message);

systemError.eventToTrigger = DELIVERY_STATES.ERRORED.eventToTrigger;

throw systemError;

}

return isDeliverySuccessful

? DELIVERY_STATES.SUCCESS : DELIVERY_STATES.FAILURE;

};

The possible delivery states include:

const DELIVERY_STATES = {

SUCCESS: {

message: 'The delivery was successful',

eventToTrigger: 'dlvry_success',

},

FAILURE: {

message: 'Delivery attempt failed',

eventToTrigger: 'dlvry_failed',

},

ERRORED: {

message: 'System error occurred',

eventToTrigger: 'dlvry_error',

},

};

Next, we set up the delivery event emitter:

const deliveryEvent = new EventEmitter();

deliveryEvent.on(DELIVERY_STATES.ERRORED.eventToTrigger, ({ message }) => {

console.error(message);

});

deliveryEvent.on(DELIVERY_STATES.FAILURE.eventToTrigger, ({ message }) => {

console.warn(message);

});

deliveryEvent.on(DELIVERY_STATES.SUCCESS.eventToTrigger, ({ message }) => {

console.info(message);

});

try {

const deliveryStatus = checkDeliveryStatus();

const { message, eventToTrigger } = deliveryStatus;

deliveryEvent.emit(eventToTrigger, { message });

} catch (error) {

const {

message = 'Unknown Error Occurred',

eventToTrigger = DELIVERY_STATES.ERRORED.eventToTrigger,

} = error;

deliveryEvent.emit(eventToTrigger, { message });

}

This logic demonstrates how random factors can yield different states, all managed efficiently through an event-driven approach.

The second video titled "Node.js 'Event Emitters' Explained" provides further insights into the mechanics of event emitters.

Conclusion

In conclusion, we have examined the principles of event-driven programming and its implementation in Node.js. This pattern is especially effective in asynchronous settings, particularly in a single-threaded language like JavaScript, helping to prevent the creation of thread-blocking code.

Thank you for engaging with this content! We hope you found it informative. Feel free to connect with us for more insights and resources.

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Exploring Exoplanets: Unraveling the Mysteries of Life in Space

Discover the fascinating realm of exoplanets and their implications for extraterrestrial life in the universe.

Before Greta Thunberg: The Legacy of Rachel Carson and Environmentalism

Rachel Carson's pioneering work in environmentalism laid the groundwork for modern sustainability movements, highlighting the dangers of pesticide use.

# Why Millennials Appear Younger Than Gen Z: The Surprising Truth

Explore the reasons behind the perception that Millennials look younger than Gen Z, from social media stress to self-care practices.