前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【JavaScript】EventEmitter的前端实现

【JavaScript】EventEmitter的前端实现

作者头像
啦啦啦321
发布2022-03-24 08:31:14
1.1K0
发布2022-03-24 08:31:14
举报

EventEmitter简介

EventEmitter是Node.js的内置模块events提供的一个类,它是Node事件流的核心,EventEmitter是服务端的东西,

前端已经有event-emitter的npm库

地址: https://www.npmjs.com/package/event-emitter

高级浏览器也有原生提供的EventTarget这种实现事件监听和触发的API

地址: https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget

但是它们和Node.js的事件API都有或多或少的区别,今天我们就来实现一个前端版本的EventEmitter

我本章demo的github地址如下

https://github.com/penghuwan/event-emitter

API介绍

我们要实现的API有:

  • on(event, listener):为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数。
  • emit(event, [arg1], [arg2]): 按监听器的顺序执行执行每个监听器
  • addListener(event, listener):on的同名函数(alias)
  • once(event, listener): 和on类似,但只触发一次,随后便解除事件监听
  • removeListener(event, listener): 移除指定事件的某个监听回调
  • removeAllListeners([event]):移除指定事件的所有监听回调
  • setMaxListeners(n):用于提高监听器的默认限制的数量。(默认10监听回调个产生警告)
  • listeners(event): 返回指定事件的监听器数组。

为了保证兼容性和简单性,下面的编码全部基于ES5语法实现

构造函数

首先我们需要写一个EventEmitter构造函数,给它设置两个属性listeners和maxListener

代码语言:javascript
复制
function EventEmitter() {
    this.listeners = {};
    this.maxListener = 10;
}

listeners用于存放事件监听器函数,结构如下:

代码语言:javascript
复制
{
  "event1": [f1,f2,f3],
  "event2": [f4,f5],
  ...
}

而maxListener 是设置的某个事件能够添加的监听器的最大数量,超过这个值,需要在控制台输出警告,但不会报错阻止。按照Node的设计,这个值能够通过setMaxListeners动态调整

on方法

  1. 判断该事件的监听器数量是否已超限,超限则报警告
  2. 判断该事件监听器数组是否初始化,若未初始化,则将listeners[event]初始化为数组,并加入监听器cb
  3. 若监听器数组已经被初始化,则判断数组中是否已存在cb,不存在则添加,已存在则不做操作。
  4. 指定addListener等于on方法
代码语言:javascript
复制
EventEmitter.prototype.on = function (event, cb) {
    var listeners = this.listeners;
    if (listeners[event] && listeners[event].length >= this.maxListener) {
        throw console.error('监听器的最大数量是%d,您已超出限制', this.maxListener)
    }
    if (listeners[event] instanceof Array) {
        if (listeners[event].indexOf(cb) === -1) {
            listeners[event].push(cb);
        }
    } else {
        listeners[event] = [].concat(cb);
    }
}

EventEmitter.prototype.addListener = EventEmitter.prototype.on;

emit方法

  1. 通过Array.prototype.slice.call(arguments)取出方法的参数列表args,(因为考虑简单性和兼容性所以采用ES5的冗长编码方式)
  2. 调用args.shift踢掉数组第一个参数即event,留下来的这些是要传给监听器的
  3. 遍历监听器,通过apply方法把上面得到的args参数传进去
代码语言:javascript
复制
EventEmitter.prototype.emit = function (event) {
    var args = Array.prototype.slice.call(arguments);
    args.shift();
    this.listeners[event].forEach(cb => {
        cb.apply(null, args);
    });
}

removeListener方法

  1. 通过indexOf确定监听器回调在数组listeners[event]中的位置
  2. 通过splice(i,1)删除之
代码语言:javascript
复制
EventEmitter.prototype.removeListener = function (event, listener) {
    var listeners = this.listeners;
    var arr = listeners[event] || [];
    var i = arr.indexOf(listener);
    if (i >= 0) {
        listeners[event].splice(i, 1);
    }
}

once方法

once方法是on方法和removeListener方法的结合:用on方法监听,在回调结束的最后位置,通过removeListener删掉监听函数自身

代码语言:javascript
复制
EventEmitter.prototype.once = function (event, listener) {
    var self = this;
    function fn() {
        var args = Array.prototype.slice.call(arguments);
        listener.apply(null, args);
        self.removeListener(event, fn);
    }
    this.on(event, fn)
}

removeAllListener方法

清空listeners[event]数组

代码语言:javascript
复制
EventEmitter.prototype.removeAllListener = function (event) {
    this.listeners[event] = [];
}

setMaxListeners方法和listeners方法

代码语言:javascript
复制
EventEmitter.prototype.listeners = function (event) {
    return this.listeners[event];
}

EventEmitter.prototype.setMaxListeners = function (num) {
    this.maxListener = num;
}

Github地址

https://github.com/penghuwan/event-emitter

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-08-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • EventEmitter简介
  • API介绍
  • 构造函数
  • on方法
  • emit方法
  • removeListener方法
  • once方法
  • removeAllListener方法
  • setMaxListeners方法和listeners方法
  • Github地址
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档