【ECMAScript】基于Map和Set手写一个简单EventEmitter实现事件的发布和订阅

1. 前言

        订阅/发布模式是常用的设计模式,也可以称为观察者模式。在NodeJS和前端开发中,也有很多地方有涉及,NodeJS原生自带EventEmitter、Redux等等。在实际SPA项目中,不同模块之间会需要这种设计,比如:A模块生成一条待执行命令,并不立即执行,需要B模块执行某些动作或满足某些条件,再触发执行这一条待执行命令。

        本文借鉴NodeJS的EventEmitter,基于ES6的Map和Set,自己实现一个EventEmitter,满足基本的发布/订阅功能。

2. 实现说明

实现常用功能:

  • on : 订阅一条事件,使用Set收纳事件,使用Map区分事件名称;
  • once:订阅一条一次性的事件;
  • emit : 发布事件,对由once方法订阅的事件,执行一次即清除;
  • off : 取消订阅,可以取消指定事件名称所有订阅,也可以取消指定事件名称和事件内容的订阅;
  • clear: 清理全部未发布的事件。
3. 完整源码
class EventEmitter {
    events = new Map();

    constructor() {}

    getEvents(eventName) {
        if(eventName) {
            let list = this.events.get(eventName);
            if(!list) {
                this.events.set(eventName, new Set());
                list = this.events.get(eventName);
            }
            return list;
        } else {
            return this.events;
        }        
    }

    on(eventName, executor) {
        const list = this.getEvents(eventName);
        list.add(executor);
        return () => {
            list.delete(executor);
        }
    }

    once(eventname, executor) {
        executor.once = true;
        return this.on(eventname, executor);
    }

    emit(eventName) {
        let list = this.events.get(eventName);
        if(list) {
            for(const handler of list) {
                try {
                    handler();
                } catch(e) {
                    console.log(e);
                }
                if(handler.once) {
                    list.delete(handler);
                }
            }
        }
    }

    off(eventName, executor) {
        let list = this.events.get(eventName);
        if(list) {
            if(executor) {
                list.delete(executor);
            } else {
                list.clear();
            }            
        }
    }

    clear() {
        this.events.clear();
    }
}

注:以上,如有不合理之处,还请帮忙指出,大家一起交流学习~

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值