Proper use Node.js event

Foreword

Prior to the event-driven programming became popular in the internal procedures standard method of communication is very simple: If a component wants to send a message to the other, but explicitly invoke a method on that component. But it is react with the event-driven instead of calling.

Benefits of events

This method enables more separate components. As we continue to write the program, it will recognize the entire course of events trigger them at the right time, and attach one or more event listeners for each event, which makes extensions easier. We can add more listener for a specific event, without having to modify existing listener or trigger the application section of the event. We are talking about the observer pattern.

Design an event-driven architecture

The event recognition is very important, and we do not want to eventually have to remove or replace an existing event from the system, because it might force us to remove or modify many listeners on the attached to the event. My general rule is to consider only if the triggering event in the business logic to complete the execution unit.

If you want to send a bunch of different e-mail after user registration. The registration process itself may involve many complex steps and queries, but from a business perspective, this is just one step. Each e-mail to be sent is a separate step. Therefore, once the registration is complete immediately release event is of great significance. So we attach multiple listeners, each listener is responsible for sending one type of e-mail.

Node asynchronous event-driven architecture has a number of objects are called "emitters" of. They issued a named event, these events will call a function is called "listener" is. All objects emit events are  EventEmitter  instance of the class. Use it, we can create your own events:

one example

Let's use the built-in events module (I suggest you look at this document: https://nodejs.org/api/events ...) in order to gain access to the EventEmitter.

const EventEmitter = require('events');

const myEmitter = new EventEmitter();

module.exports = myEmitter;

This is part of our server-side program, which is responsible for receiving HTTP requests, save the new user and signaling events:

const myEmitter = require('./my_emitter');

// Perform the registration steps

// Pass the new user object as the message passed through by this event.
myEmitter.emit('user-registered', user);

A listener additional separate modules:

const myEmitter = require('./my_emitter');

myEmitter.on('user-registered', (user) => {
// Send an email or whatever.
});

The strategy and implementation of Separation is a very good practice. In this case, the strategy means what subscribe to the listener what events. It means the listener to realize themselves.

const myEmitter = require('./my_emitter');
const sendEmailOnRegistration = require('./send_email_on_registration');
const someOtherListener = require('./some_other_listener');

myEmitter.on('user-registered', sendEmailOnRegistration);
myEmitter.on('user-registered', someOtherListener);
module.exports = (user) => {
// Send a welcome email or whatever.
}

This separation makes listener may be reused, it can be attached to the other events of the same message sent (user object). It is also important when a plurality of listener is attached to a single event, which will be performed in the additional synchronization sequence. Therefore someOtherListener will complete the run after execution sendEmailOnRegistration.

However, if you want your listener to run asynchronously, just use setImmediate packing their implementation, as follows:

module.exports = (user) => {
setImmediate(() => {
// Send a welcome email or whatever.
});
}

Let Your Listeners kept simple

When writing listener should adhere to the principle of single responsibility. A listener should do one thing and get things done. For example: To avoid writing too many conditions and the listener to decide what to do based on the data (message) event came. Use different events in this case would be more appropriate:

const myEmitter = require('./my_emitter');

// Perform the registration steps

// The application should react differently if the new user has been activated instantly.
if (user.activated) {
myEmitter.emit('user-registered:activated', user);

} else {
myEmitter.emit('user-registered', user);
}
const myEmitter = require('./my_emitter');
const sendEmailOnRegistration = require('./send_email_on_registration');
const someOtherListener = require('./some_other_listener');
const doSomethingEntirelyDifferent = require('./do_something_entirely_different');

myEmitter.on('user-registered', sendEmailOnRegistration);
myEmitter.on('user-registered', someOtherListener);

myEmitter.on('user-registered:activated', doSomethingEntirelyDifferent);
view raw

Listener clear separation if necessary

In the previous example, we are completely independent of listener function. But (this time is a way), you must manually separated from the subscribed event in the case of listener associated with the object. Otherwise, the object will never be garbage collected, because part of the object (listener) will continue to be references to external objects (emitter), there may be a memory leak.

For example, if we are developing a chat program, and hope that when a new message arrives a user enters a chat room, display notifications should be located inside the user object itself, we might do:

class ChatUser {

displayNewMessageNotification(newMessage) {
// Push an alert message or something.
}

// `chatroom` is an instance of EventEmitter.
connectToChatroom(chatroom) {
chatroom.on('message-received', this.displayNewMessageNotification);
}

disconnectFromChatroom(chatroom) {
chatroom.removeListener('message-received', this.displayNewMessageNotification);
}
}

When the user closes his label or temporarily disconnect from the Internet, we may want to initiate a callback on the server side, it was just to inform other users offline. Of course, at this time call displayNewMessageNotification offline user does not make any sense. Unless we remove it, otherwise it will continue to be used to call a new message. Failure to do so, in addition to unnecessary calls outside the user object will be permanently retained in memory. So should call disconnectFromChatroom on the server side callback when the user is offline.

Precautions

If you are not careful, even a loosely coupled event-driven architecture can lead to increased complexity may result in dependency tracking system becomes very difficult. If we send events from inside the listener, the program will be particularly prone to such problems. This may trigger unexpected chain of events.

 

You may also be interested in the article:

Article simultaneous release:  https://www.geek-share.com/detail/2769911794.html

Guess you like

Origin www.cnblogs.com/xiaoqifeng/p/10930206.html