闭包实现观察者模式是微模块间低耦合通信的轻量方案,通过私有消息映射表支持注册、触发与移除,无需类或第三方库,适合微前端等场景。

用闭包实现观察者模式,是微模块间建立低耦合信号通讯的轻量级方案。它不依赖类、继承或第三方库,靠函数作用域和引用捕获就能完成订阅-通知逻辑,特别适合前端微前端、插件系统或小型状态管理场景。
闭包版观察者的核心结构
核心是一个封闭的消息中心,内部维护私有消息映射表(type → [fn]),所有方法都通过闭包共享该状态,外部无法直接访问或篡改:
- regist(type, fn):按消息类型注册处理函数,自动创建类型队列或追加到已有队列
- fire(type, ...args):触发指定类型的所有监听函数,并透传参数
- remove(type, fn):从对应类型队列中移除指定函数(需支持精确比对)
为什么闭包比类更适配微模块通信
微模块通常彼此独立打包、动态加载,没有统一基类或接口约束。闭包方案天然规避了类型依赖:
- 模块只需引入一个极简的
Observer函数,无需 import 抽象类或 Observer 接口 - 每个模块注册的是纯函数,不绑定 this 或生命周期,可自由组合、复用、测试
- 消息类型是字符串,模块间靠约定而非代码耦合,比如统一用
"user:login"而非UserLoginEvent类
实际使用时的关键细节
真正落地时,几个细节决定是否稳定可用:
- 注册函数建议用
WeakMap或标记属性(如fn.__id = Symbol())解决 remove 时的函数引用比对问题 - fire 执行应 try/catch 单个监听器,避免一个报错中断其余模块响应
- 若模块有销毁逻辑(如组件卸载),应在卸载前调用 remove,防止内存泄漏
- 可扩展支持通配符(如
"data:*")或优先级队列,满足进阶路由式分发需求
一个可直接粘贴的精简实现
以下代码无依赖、不到 30 行,已在多个微前端项目中验证:
const Observer = (() => {
const messages = {};
return {
regist(type, fn) {
if (!messages[type]) messages[type] = [];
messages[type].push(fn);
},
fire(type, ...args) {
(messages[type] || []).forEach(fn => {
try { fn(...args); } catch (e) { console.warn('Observer error:', e); }
});
},
remove(type, fn) {
if (messages[type]) {
messages[type] = messages[type].filter(f => f !== fn);
}
}
};
})();
模块 A 发送信号:Observer.fire('auth:logout', { reason: 'timeout' });
模块 B 订阅响应:Observer.regist('auth:logout', handleLogout);

















