Interesting events Nodejs modules,

Event-driven model

Nodejs uses an event-driven, non-blocking IO model. eventsEvent-driven module is the core module. Many built-in modules are inherited events.EventEmitter.

Own without having to manually implement this design pattern, the direct successor EventEmitterto. code show as below:

const { EventEmitter } = require("events");

class MyEmitter extends EventEmitter {}

const ins = new MyEmitter();
ins.on("test", () => {
    console.log("emit test event");
});
ins.emit("test");

Elegant error handling

According to the document, should EventEmitter instance of errorthe event is a special event. Recommended practice : after instance creation, should be registered immediately errorevent.

const ins = new MyEmitter();
ins.on("error", error => {
    console.log("error msg is", error.message);
});

Registration errorafter the event, I had the understanding that all events back out logic errors are caught inside EventEmitter, and trigger inside the errorevent.

That the following code will print: "error msg is a is not defined".

ins.on("test", () => {
    console.log(a);
});

ins.emit("test");

However, the error did not capture, direct throw an exception. Thus, EventEmitter in the implementation of internal logic, and no try-catch. For this reason, see the Node Issue . Simply put, Error and Exception not exactly the same.

If the normal idea, do not want every time one sets out try-catchhow it should do it? My practice is to
add a prototype on EventEmitter chain safeEmitfunction.

EventEmitter.prototype.safeEmit = function(name, ...args) {
    try {
        return this.emit(name, ...args);
    } catch (error) {
        return this.emit("error", error);
    }
};

Thus, Exception piece of code will run before being captured, and trigger errorevents. Output of the previous piece of code becomes:

error msg is a is not defined

Queue Listener sequential processing

For the same event, when it is triggered, the execution order function is a function of the time of the binding order. Library provides official emitter.prependListener()and emitter.prependOnceListener()two interfaces, allowing new listeners added directly to the head of the queue.

But if you want the new listener into any position in any listener queue it? A chain on a prototype packaging insertListenermethod.

EventEmitter.prototype.insertListener = function(
    name,
    index,
    callback,
    once = false
) {
    // 如果是once监听器,其数据结构是 {listener: Function}
    // 正常监听器,直接是 Function
    const listeners = ins.rawListeners(name);
    const that = this;
    // 下标不合法
    if (index > listeners.length || index < 0) {
        return false;
    }
    // 绑定监听器数量已达上限
    if (listeners.length >= this.getMaxListeners()) {
        return false;
    }
    listeners.splice(index, 0, once ? { listener: callback } : callback);
    this.removeAllListeners(name);
    listeners.forEach(function(item) {
        if (typeof item === "function") {
            that.on(name, item);
        } else {
            const { listener } = item;
            that.once(name, listener);
        }
    });
    return true;
};

Use, the effect is as follows:

const ins = new MyEmitter();
ins.on("error", error => {
    console.log("error msg is", error.message);
});

ins.on("test", () => {
    console.log("test 1");
});

ins.on("test", () => {
    console.log("test 2");
});

// 监听器队列中插入新的监听器,一个是once类型,一个不是once类型
ins.insertListener(
    "test",
    0,
    () => {
        console.log("once test insert");
    },
    true
);
ins.insertListener("test", 1, () => {
    console.log("test insert");
});

Two successive calls ins.emit("test"), the resulting output is as follows:

# 第一次
once test insert
test insert
test 1
test 2
# 第二次: once 类型的监听器调用一次后销毁
test insert
test 1
test 2

Memory management and prevent leakage

When the binding event listeners, if the listener is not remove, then the risk of memory leaks exist.

I know that the common practice is as follows:

  • Often CR, remove unwanted event listeners
  • By oncebinding the listener, after calling time, the listener is automatically removed
  • [Recommended] hack a saferEventEmitter

Guess you like

Origin www.cnblogs.com/jyfg/p/12177620.html