npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@redm/eventemitter

v0.9.0

Published

An EventEmitter Class. Support add event parent.

Downloads

2

Readme

EventEmitter

释疑:为何造轮子?

乍一看,这和其他的 EventEmitter 的功能没什么两样,同样支持 on / once / off / emit 此类方法。那为什么还要造轮子?

先把原因概括下,下面会详细说明:这个 EE 增加了添加父级事件的方法,即支持多层事件传递。

接下来详细说明多层事件传递是什么?先举个发动机 engine 和 汽车 car 的栗子说明:

我们用 EE 创建了一个 engine 对象,engine 的某个行为会触发了一个启动事件 'start'。接着我们又用 EE 创建一个 car 对象,我希望 engine 在触发 'start' 事件时,car 也触发这个启动 'start' 事件。(很好理解发动机启动了,汽车也就启动了。)

通常 EE 的实现:

const engine = new EventEmitter();
const car = new EventEmitter();
// 监听 engine 的 start 事件 
engine.on('start', () => {
    // 你 start,我也 start
    car.emit('start', {});
});

engine.emit('start', {});

接着我们思考下面两个问题:

  1. 如果 engine 还会触发 stop / break / error 等事件,car 也希望通通拥有。
  2. 如果我们在 car 上再增加一个里程表 odometer,当 car 启动以后,odometer 也跟随启动。

这两个问题如果继续使用上面的方式实现,代码就掉入了类似 callback hell 的深渊。

于是我们想到了一个打破深渊的办法 —— 增加一个 addEventParent 方法来实现 多层事件传递,即通过添加一个父级对象,将当前对象的事件冒泡到他的父级上。
我们来看下它的用法:

const engine = new EventEmitter();
const car = new EventEmitter();
// 通过 addEventParent 为 engine 添加一个父级事件节点 car,当 engine 派发一个事件时,可以将事件冒泡至他的父级 car 上。
engine.addEventParent(car);
// 为了使事件可以冒泡至父级,调用 emit 时,通过第三个参数控制事件的冒泡。
// 发动机启动会传递至车辆上
engine.emit('start', {}, true);

// 如果希望里程表 odometer 也获得 start 事件,为 car 添加父级事件节点 odometer 即可
const odometer = new EventEmitter();
car.addEventParent(odometer);

好了,至此对于造轮子的原因解释完毕。如果你的实践中有这种多层事件传递的场景,可以考虑使用这个 EE。

最后要感谢 leaflet.js,这种多层事件传递实际是参考了 leaflet 中的实现。并不是我的原创。

API 文档

1. 创建 EE

const ee = new EventEmitter()

2. 继承 EE

如果您使用了 ES6 的 Class 特性,可以考虑将 EE 作为父类继承,这样可以使得您的类型拥有 EE 的所有特性。

import { EventEmitter } from 'EventEmitter'

class Car extends EventEmitter {
    constructor() { }
    
    doSome() {
        this.emit('some')
    }
}

3. 事件绑定 on(type, fn, content?) / once(type, fn, content?)

参数:

  • type {string} 事件名称,多个事件名可用空格分开
  • fn {Function} 回调函数
  • content {*=} fn 回调上下文

其中 fn 回调参数 Event 结构为:

  • event.type {string} 事件名
  • event.target {EventEmitter} 触发事件的对象

返回:

  • EventEmitter
const ee = new EventEmitter();
// 支持空格分割多个事件
ee.on('load start stop', ev => { })

// 用后即焚
ee.once('load', ev => { })

4. 事件解绑 off(type?, fn?, content?)

参数:

  • type {string=} 事件名称 不设置清除全部事件
  • fn {Function=} 回调函数 不设置清除所有 type 上的 fn
  • content {*=} fn 回调上下文

返回:

  • EventEmitter

5. 触发事件 emit(type, obj?, propagate?)

参数:

  • type {string} 事件名
  • obj {object=} 参数,会被 merge 到 event 中。注意 object 中不要使用 typetarget 关键词,否则会覆盖原始参数。
  • propagate {boolean=} 当前事件是否冒泡至父级事件节点。默认不冒泡。

返回:

  • EventEmitter

6. 添加父级事件节点 addEventParent(ee, fn?)

参数:

  • ee {EventEmitter} 为当前对象添加父级节点,当前对象事件触发后,可以冒泡至父级节点
  • fn {Function=} 触发父级节点时,可通过该回调函数修改原有回调参数。需要将修改后的参数返回。

返回:

  • EventEmitter

依旧用发动机 engine 和汽车 car 这个场景说明:

1. engine start 后,car 也跟着 start。并且获取了 engine 派发的信息。
const engine = new EventEmitter();
const car = new EventEmitter();
car.on('start', ev => {
    console.log('car: ', ev.msg);
});
engine.addEventParent(car);

engine.emit('start', {
    msg: '我发动了!'
}, true);

// log: "car: 我发动了!"
2. engine start 后,car 也跟着 start,并且添加了 car 自己特有的的信息。
// 创建同上
car.on('start', ev => {
    console.log('car: ', ev.msg);
    console.log('car name: ', ev.name);
});
engine.addEventParent(car, ev => {
    ev.name = 'Benz';
    return ev;
});

engine.emit('start', {
    msg: '我发动了!'
}, true);

// log: "car: 我发动了!"
// log: "car name: Benz";

至此关于 EE 的全部就介绍完了,希望如果这个 EE 对你有帮助,欢迎使用。:D