node中events实现原理

640?wx_fmt=png

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 的核心原理,其设计思想还是发布订阅。

640?wx_fmt=png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值