当前位置: 首页 > 工具软件 > Copy Events > 使用案例 >

node中events实现原理

南宫正阳
2023-12-01

events称为事件触发器,on() 用于注册监听器, emit() 用于触发事件。用例如下:

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('触发事件');
});
myEmitter.emit('event');

这就events模块的使用,node中很多模块都继承于它,比如构建一个HTTP服务时处理post请求数据。

const http = require('http');

const server = http.createServer((req, res) => {
  const buffers = [];
  req.on('data', function (chunk) {
    buffers.push(chunk);
  });
  req.on('end', function () {
    const content = Buffer.concat(buffers).toString();
    console.log(content)
  });
})
server.listen(8080)

在处理post数据时通过on注册了dataend事件,每当请求到来http模块内部会通过emit触发这两个事件。

现在已经掌握了events模块的使用,下面介绍其实现原理。

const EventEmitter = {
  _events = {
    data: () => {},
    end: () => {}
  },
  _eventsCount: 2,
}

events模块内部会维护一个这样的对象,_events是保存事件名称和事件处理函数的对应关系,_eventsCount是保存事件的个数。

第一步初始化这个对象

function EventEmitter() {
  EventEmitter.init.call(this);
}


EventEmitter.init = function () {
  if (this._events === undefined) {
    this._events = Object.create(null);
    this._eventsCount = 0;
  }
}

第二步实现on注册事件的方法

EventEmitter.prototype.addListener = function addListener(type, listener) {
  return _addListener(this, type, listener)
}

function _addListener(target, type, listener) {
  var events;
  var existing;
  checkListener(listener)
  events = target._events;
  if (events === undefined) {
    events = target._events = Object.create(null);
    target._eventsCount = 0;
  } else {
    existing = events[type]
  }
  if (existing === undefined) {
    events[type] = listener;
    ++target._eventsCount;
  } else {
    if (typeof existing === 'function') {
      existing = events[type] = [existing, listener]
    } else {
      existing.push(listener)
    }
  }
  return target
}

EventEmitter.prototype.on = EventEmitter.prototype.addListener

第三步实现emit触发事件的方法

EventEmitter.prototype.emit = function emit(type, ...args) {
  const events = this._events;
  const handler = events[type];
  if (handler === undefined) {
    return false
  }
  if (typeof handler === 'function') {
    Reflect.apply(handler, this, args)
  } else {
    let len = handler.length;
    const listeners = arrayClone(handler, len);
    for (var i = 0; i < len; ++i) {
      Reflect.apply(listeners[i], this, args)
    }
  }
}

function arrayClone(arr, n) {
  var copy = new Array(n);
  for (var i = 0; i < n; ++i) {
    copy[i] = arr[i];
  }
  return copy;
}

现在已经基本完成了events的核心原理,其设计思想还是发布订阅。

 类似资料: