EventEmitter

Knowledge of graphic

  • on
  • emit
  • off
  • once
  • newListener

1. On and emit

1.1 the use of

const EventEmitter = require('events');
const util = require('util');

function Baby() {}

/ / inheritance
util.inherits(Baby, EventEmitter);

// Create an instance
const baby = new Baby();
/ / subscribe
baby.on('cry'.(. args) = > {
    console.log(... args); })/ / subscribe
baby.on('cry'.(. args) = > {
    console.log(... args); })/ / release
baby.emit('cry'.'I'm hungry'.'I'm thirsty')

//=> Output result
// I'm hungry. I'm thirsty
// I'm hungry. I'm thirsty
Copy the code

1.2 implementation

function EventEmitter() {
    this._events = {}
}

EventEmitter.prototype.on = function(eventName, callback) {
    //this._events does not exist
    if (!this._events) this._events = {};
    // Check whether the event name already exists
    if (!this._events[eventName]) {
        this._events[eventName] = [callback];
    } else {
        this._events[eventName].push(callback);
    }
}

EventEmitter.prototype.emit = function(eventName, ... args) {
    if (!this._events) this._events = {};
    / / release
    if (this._events[eventName]) {
        this._events[eventName].forEach(fn= > fn(...args));
    }
}

module.exports = EventEmitter;
Copy the code

2. off

2.1 the use of

const EventEmitter = require('events');
const util = require('util');

function Baby() {}

/ / inheritance
util.inherits(Baby, EventEmitter);

// Create an instance
const baby = new Baby();
/ / subscribe
baby.on('cry'.(. args) = > {
    console.log(... args); })function eat() {
    console.log('I want to eat.')}/ / subscribe
baby.on('cry', eat)

// Unsubscribe
baby.off('cry', eat)

/ / release
baby.emit('cry'.'I'm hungry')

//=> Output result
/ / I'm hungry
Copy the code

2.2 implementation

EventEmitter.prototype.off = function(eventName, callback) {
    if (!this._events) this._events = {};
    if (this._events[eventName]) {
        this._events[eventName] = this._events[eventName].filter(event= > event !== callback);
    }
}
Copy the code

3. once

3.1 the use of

const EventEmitter = require('events');
const util = require('util');

function Baby() {}

/ / inheritance
util.inherits(Baby, EventEmitter);

// Create an instance
const baby = new Baby();

/ / subscribe
baby.on('cry'.(. args) = > {
    console.log(... args); })// Subscribe once. First emit will be executed. Subsequent emit will not be executed
baby.once('cry'.() = > {
    console.log('I want to eat.');
})

baby.emit('cry'.'I'm hungry');
baby.emit('cry'.'I'm hungry');

//=> Output result
/ / I'm hungry
// I want to eat
/ / I'm hungry
Copy the code

3.2 implementation

// The implementation is still subscribed, but the subscribed callback is destroyed when it needs to be called
EventEmitter.prototype.once = function(eventName, callback) {
    if (!this._events) this._events = {};
    const once = (. args) = > { // Arrow function in case this points to something wrongcallback(... args);this.off(eventName, once); // We need to destroy once, because on is once
    }
    this.on(eventName, once)
}
Copy the code

In fact, such once is not complete, there may be a call once, and then call off, in this case, there will be a call once situation, but the source code did not tune once

Once modified

EventEmitter.prototype.once = function(eventName, callback) {
    if (!this._events) this._events = {};
    const once = (. args) = >{ callback(... args);this.off(eventName, once)
    }
    once.l = callback; // To prevent the off method from being called after once, this will need to be cleared with this flag
    this.on(eventName, once)
}
Copy the code

Off to modify

EventEmitter.prototype.off = function(eventName, callback) {
    if (!this._events) this._events = {};
    if (this._events[eventName]) {
        this._events[eventName] = this._events[eventName].filter(event= >event ! == callback && event.l ! == callback); }}Copy the code

4. newListener

NewListener calls callback when subscribing in addition to itself, passing the call type

4.1 the use of

const EventEmitter = require('events');
const util = require('util');

function Baby() {}

/ / inheritance
util.inherits(Baby, EventEmitter);

// Create an instance
const baby = new Baby();

baby.on('newListener'.(type) = > {
    console.log('newListener:', type)
})

/ / subscribe
baby.on('cry'.(. args) = > {
    console.log(... args); }) baby.once('cry'.() = > {
    console.log('I want to eat.');
});

/ / = > output
/ / newListener: cry
/ / newListener: cry
Copy the code

4.2 implementation

EventEmitter.prototype.on = function(eventName, callback) {
    // Call on with no _events attribute, add one dynamically
    if (!this._events) this._events = {};

    //newListenr is triggered every time on
    if(eventName ! = ='newListener') {
        this.emit('newListener', eventName);
    }

    // Check that there is already a corresponding event name
    if (!this._events[eventName]) {
        this._events[eventName] = [callback];
    } else {
        this._events[eventName].push(callback); }}Copy the code

All the code

function EventEmitter() {
    this._events = {}; // Instance properties
}

/ / subscribe
EventEmitter.prototype.on = function(eventName, callback) {
    // Call on with no _events attribute, add one dynamically
    if (!this._events) this._events = {};

    //newListenr is triggered every time on
    if(eventName ! = ='newListener') {
        this.emit('newListener', eventName);
    }

    // Check that there is already a corresponding event name
    if (!this._events[eventName]) {
        this._events[eventName] = [callback];
    } else {
        this._events[eventName].push(callback); }}/ / release
EventEmitter.prototype.emit = function(eventName, ... args) {
    // Prevent this._events from being null when first published
    if (!this._events) this._events = {};
    this._events[eventName].forEach(event= >event(... args)); }// Unsubscribe
EventEmitter.prototype.off = function(eventName, callback) {
    if (!this._events) this._events = {};
    if (this._events[eventName])
        this._events[eventName] = this._events[eventName].filter(event= >event ! == callback && event.l ! == callback); }// Subscribe once
EventEmitter.prototype.once = function(eventName, callback) {
    if (!this._events) this._events = {};
    const once = (. args) = >{ callback(... args);this.off(eventName, once)
    }
    once.l = callback; // To prevent the off method from being called after once, this will need to be cleared with this flag
    this.on(eventName, once)
}

module.exports = EventEmitter;
Copy the code