# chanjs Event 类使用文档
## 概述
`chanjs` 中的 `Event` 类基于 Node.js 内置 `EventEmitter` 封装，提供轻量级的事件订阅/发布能力，支持事件注册、触发、注销等核心操作，接口简洁且保持与原生 `EventEmitter` 兼容，适用于业务中解耦组件间的通信场景。

## 前置准备
### 1. 引入方式
```javascript
import { Event } from "chanjs";

// 方式1：创建实例使用
const event = new Event();

// 方式2：直接使用内置单例（推荐全局通信）
import { event } from "chanjs";
```

### 2. 通用约定
- 事件名（`eventName`）建议使用**语义化字符串**（如 `user:login`、`order:created`），避免命名冲突
- 监听器函数（`listener`）接收的参数为触发事件时传入的 `data`，支持任意类型数据
- 所有方法均返回当前 `Event` 实例，支持**链式调用**

## 核心方法使用指南
### 1. 注册事件监听器 - on
#### 作用
为指定事件注册一个持久化的监听器（事件触发时会执行该函数），支持为同一事件注册多个监听器。
#### 传参格式
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| eventName | String | 是 | 事件名称（如 `user:login`） |
| listener | Function | 是 | 事件触发时执行的回调函数，参数为触发事件传入的 `data` |
#### 使用示例
```javascript
// 注册单个事件监听器
event.on("user:login", (data) => {
  console.log("用户登录事件触发：", data);
  // 业务逻辑：记录登录日志、更新最后登录时间等
});

// 为同一事件注册多个监听器
event.on("order:created", (orderData) => {
  console.log("订单创建-日志记录：", orderData.id);
});
event.on("order:created", (orderData) => {
  console.log("订单创建-消息推送：", orderData.userId);
});

// 链式调用注册多个事件
event
  .on("article:add", (article) => console.log("新增文章：", article.title))
  .on("article:delete", (id) => console.log("删除文章ID：", id));
```

### 2. 触发事件 - emit
#### 作用
触发指定名称的事件，执行该事件下所有已注册的监听器，并传递数据给监听器函数。
#### 传参格式
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| eventName | String | 是 | 要触发的事件名称 |
| data | Any | 否 | 传递给监听器的事件数据（任意类型：对象、数组、基本类型等） |
#### 使用示例
```javascript
// 触发用户登录事件，传递用户数据
event.emit("user:login", {
  userId: 1001,
  username: "test_user",
  loginTime: new Date(),
  ip: "127.0.0.1"
});

// 触发订单创建事件，传递订单数据
const orderData = {
  id: "ORD20260323001",
  userId: 1001,
  amount: 99.9,
  createTime: new Date()
};
event.emit("order:created", orderData);

// 触发无数据的事件
event.emit("system:refresh");
```

### 3. 注销事件监听器 - off
#### 作用
注销指定事件下的某个具体监听器，仅移除该监听器，不影响同一事件的其他监听器。
#### 传参格式
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| eventName | String | 是 | 事件名称 |
| listener | Function | 是 | 要注销的监听器函数（需与注册时的函数引用一致） |
#### 使用示例
```javascript
// 定义可复用的监听器函数
const loginListener = (data) => {
  console.log("用户登录监听器：", data);
};

// 注册监听器
event.on("user:login", loginListener);

// 触发事件（监听器会执行）
event.emit("user:login", { userId: 1001 });

// 注销指定监听器
event.off("user:login", loginListener);

// 再次触发事件（该监听器不再执行）
event.emit("user:login", { userId: 1001 });

// 链式注销多个监听器
const articleAddListener = (data) => console.log("新增文章：", data);
const articleDelListener = (id) => console.log("删除文章：", id);

event
  .on("article:add", articleAddListener)
  .on("article:delete", articleDelListener)
  .off("article:add", articleAddListener)
  .off("article:delete", articleDelListener);
```

### 4. 注销所有事件监听器 - removeAllListeners
#### 作用
注销指定事件下的**所有**监听器，或注销所有事件的所有监听器（不传参数时）。
#### 传参格式
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| eventName | String | 否 | 事件名称（不传则注销所有事件的监听器） |
#### 使用示例
```javascript
// 注册多个监听器
event
  .on("order:created", (data) => console.log("监听器1：", data))
  .on("order:created", (data) => console.log("监听器2：", data))
  .on("user:login", (data) => console.log("登录监听器：", data));

// 注销order:created事件的所有监听器
event.removeAllListeners("order:created");
// 触发该事件（无监听器执行）
event.emit("order:created", { id: "ORD001" });

// 注销所有事件的所有监听器（全局清空）
event.removeAllListeners();
// 触发任何事件都无监听器执行
event.emit("user:login", { userId: 1001 });
```

## 高级使用场景
### 场景1：一次性事件监听（扩展）
原生 `EventEmitter` 支持 `once` 方法（注册仅执行一次的监听器），`Event` 类继承该能力，可直接使用：
```javascript
// 注册仅执行一次的监听器
event.once("config:update", (config) => {
  console.log("配置更新（仅执行一次）：", config);
});

// 第一次触发（监听器执行）
event.emit("config:update", { theme: "dark" });
// 第二次触发（监听器已自动注销，不执行）
event.emit("config:update", { theme: "light" });
```

### 场景2：业务模块解耦示例
```javascript
// 模块A：用户模块
import { event } from "chanjs";

class UserModule {
  async login(username, password) {
    // 登录逻辑
    const user = { id: 1001, username };
    // 触发登录事件，无需关心其他模块逻辑
    event.emit("user:login", user);
    return user;
  }
}

// 模块B：日志模块
import { event } from "chanjs";

class LogModule {
  constructor() {
    // 监听登录事件，记录日志
    event.on("user:login", (user) => {
      console.log(`[LOG] 用户${user.username}(${user.id})于${new Date()}登录`);
    });
  }
}

// 模块C：消息模块
import { event } from "chanjs";

class MessageModule {
  constructor() {
    // 监听登录事件，推送消息
    event.on("user:login", (user) => {
      console.log(`[MSG] 向用户${user.id}推送登录成功消息`);
    });
  }
}

// 业务入口
const userModule = new UserModule();
const logModule = new LogModule();
const messageModule = new MessageModule();

// 执行登录，自动触发日志和消息模块的逻辑
await userModule.login("test_user", "123456");
```

### 场景3：错误事件处理
```javascript
// 注册全局错误事件监听器
event.on("error", (err) => {
  console.error("全局事件错误：", err);
  // 业务逻辑：错误上报、告警等
});

// 触发错误事件（建议使用Error对象传递错误信息）
event.emit("error", new Error("订单创建失败：库存不足"));
```

## 注意事项
1. 注销监听器时，`off` 方法传入的 `listener` 必须与 `on` 注册时的函数**引用一致**，匿名函数无法被注销；
2. 事件名建议使用 `模块:动作` 的命名规范（如 `user:login`、`order:created`），避免全局命名冲突；
3. 若监听器函数执行过程中抛出异常，不会阻断其他监听器执行，但需自行捕获异常避免程序崩溃；
4. 单例 `event` 适用于全局通信，若需隔离事件作用域，可创建多个 `Event` 实例（`new Event()`）。

## 总结
1. `Event` 类核心提供 `on`（注册）、`emit`（触发）、`off`（注销）、`removeAllListeners`（清空）四个方法，覆盖事件通信全流程；
2. 基于 Node.js `EventEmitter` 实现，兼容原生方法（如 `once`），接口简洁易上手；
3. 适用于业务模块解耦场景，通过事件发布/订阅模式减少模块间直接依赖，提升代码可维护性。