Categories
Tags
Ai 生成 API学习 API简化 api请求 API调用 best-practices Blogging Caching catchTag catchTags class CLI Config context Context Context.Tag CSS Customization Demo development DocC Docker dual API Effect effect Effect.Service Effect.succeed Example extension ffmpeg filterOrFail flatMap Fuwari gen generator grep hooks HTML HTTP响应 IDE自动补全 iOS javascript JavaScript Javascript Layer.effect Layer.provide Layers Linux Markdown Mock n8n Next.js ParseError pipe pokemon PostCSS process.env progress Promise promise provideService PWA react React React Hook Form React Query React Router react-native Scheduler Schema Schema.Class security Service Worker Services SSR state-management suspense Tagged Errors TaggedError TanStack Query TanStack Start tips tryPromise tsconfig TypeScript typescript Video VS Code vscode Web API Web Development yield yt-dlp Zod 不透明类型 二叉树 代码组织 任务调度 优先级 使用服务 依赖注入 依赖管理 值语义 入门教程 最佳实践 最小堆 函数式编程 函数组合 前端 前端开发 副作用 副作用控制 可视化 可组合性 可维护性 可访问性 命令行 响应过滤 多个错误 实现 实践指南 层 层依赖 层组合 工具链 并发控制 应用架构 延迟执行 开发技巧 开发教程 开源 异步处理 异步操作 异步编程 性能优化 手写系列 排序 接口设计 插件开发 数据结构 数据获取 数据解码 数据验证 无限滚动 日历 日志分析 服务 服务依赖 服务定义 服务实现 服务提供 测试 源码分析 状态管理 环境变量 生成器 离线支持 程序分离 算法 类型安全 类型定义 类型推断 类型系统 类定义 线性代码 组合 翻译 自动化 自定义错误 表单验证 记忆化 设计模式 语义化 运维 运行时验证 部分应用 配置 配置变量 配置服务 配置管理 重构 错误处理 错误定义 错误恢复 项目设置
463 words
2 minutes
mitt 源码阅读
Waiting for api.github.com...
NOTEmitt 是一个极简的事件发布订阅库,整个源码仅有 200 字节。它提供了事件的订阅、发布和取消订阅功能,是学习发布订阅模式的绝佳案例。
将类型删除转化为 js 代码,方便阅读:
export default function mitt(
all = new Map();
): {
return {
all,
on(type, handler) {
const handlers= all!.get(type);
if (handlers) {
handlers.push(handler);
} else {
all!.set(type, [handler]);
}
},
off(type, handler) {
const handlers = all!.get(type);
if (handlers) {
if (handler) {
handlers.splice(handlers.indexOf(handler) >>> 0, 1);
} else {
all!.set(type, []);
}
}
},
emit(type, evt) {
let handlers = all!.get(type);
if (handlers) {
(handlers as EventHandlerList<Events[keyof Events]>)
.slice()
.map((handler) => {
handler(evt!);
});
}
handlers = all!.get('*');
if (handlers) {
(handlers as WildCardEventHandlerList<Events>)
.slice()
.map((handler) => {
handler(type, evt!);
});
}
}
};
}TIPmitt 的核心是使用 Map 来存储事件和对应的处理函数列表。初始化时可以预设一些事件,以
{key: [...handlers]}的形式存在。
核心功能解析
1. 订阅事件 (on)
on(type, handler)NOTE
type: 事件类型handler: 事件处理函数- 如果该事件类型已存在处理函数列表,则将新的处理函数追加到列表中
- 如果是首次订阅该事件,则创建新的处理函数列表
2. 发布事件 (emit)
emit(type, evt)NOTE
type: 要触发的事件类型evt: 传递给处理函数的事件数据- 会触发两类处理函数:
- 指定事件类型的处理函数列表
- 通配符
*的处理函数列表(这些处理函数可以接收所有事件)
3. 取消订阅 (off)
// 取消指定处理函数
off(type, handler)
// 取消该事件类型的所有处理函数
off(type)NOTE
- 可以选择性地移除单个处理函数,或清空某个事件类型的所有处理函数
- 使用
handlers.splice(handlers.indexOf(handler) >>> 0, 1)来安全地移除指定处理函数>>> 0操作确保了在找不到处理函数时(返回 -1)不会发生错误
