JS如何实现观察者模式

观察者模式的核心在于主题直接管理并通知观察者,而发布订阅模式通过事件中心解耦发布者与订阅者;在javascript中,该模式广泛应用于dom事件、状态管理、实时数据更新等场景,其实现需注意内存泄漏、通知性能、错误处理及数据传递方式,确保系统解耦性与健壮性。

JS如何实现观察者模式

JavaScript中实现观察者模式,核心在于构建一个“主题”(Subject)对象,它负责维护一个订阅者(Observer)列表,并在自身状态发生变化时,遍历这个列表并通知所有已注册的订阅者。说白了,就是让感兴趣的对象(观察者)去“监听”另一个对象(主题)的变化,一旦有变动,主题就会告诉它们。

class Subject {    constructor() {        this.observers = []; // 存储所有观察者    }    /**     * 添加一个观察者     * @param {Function} observer - 观察者函数或对象,通常是一个回调函数     */    addObserver(observer) {        if (typeof observer === 'function' && !this.observers.includes(observer)) {            this.observers.push(observer);        } else {            // 我个人觉得,这里加个简单的错误提示或者日志会更好,            // 毕竟有时候传入的可能不是函数,或者重复添加了            console.warn('Observer must be a unique function.');        }    }    /**     * 移除一个观察者     * @param {Function} observer - 要移除的观察者     */    removeObserver(observer) {        this.observers = this.observers.filter(obs => obs !== observer);    }    /**     * 通知所有观察者状态已更新     * @param {*} data - 传递给观察者的数据     */    notify(data) {        // 有时候我会考虑是否要异步通知,避免一个耗时观察者阻塞其他,        // 但对于多数前端场景,同步通知也挺常见。        this.observers.forEach(observer => {            try {                observer(data);            } catch (error) {                // 这里捕获一下观察者执行时的错误,避免一个观察者出错导致整个通知链中断                console.error('Error notifying observer:', error);            }        });    }}// 示例用法:const mySubject = new Subject();// 定义一些观察者const observerA = (data) => {    console.log('观察者A收到通知:', data);};const observerB = (data) => {    console.log('观察者B收到通知,数据是:', data);};const observerC = (data) => {    console.log('观察者C处理数据:', JSON.stringify(data));};// 注册观察者mySubject.addObserver(observerA);mySubject.addObserver(observerB);mySubject.addObserver(observerC);console.log('--- 第一次状态变化 ---');mySubject.notify({ message: 'Hello from Subject!', timestamp: Date.now() });// 移除一个观察者mySubject.removeObserver(observerB);console.log('--- 第二次状态变化(B已移除)---');mySubject.notify('新的消息');// 尝试添加一个非函数或重复的mySubject.addObserver({}); // 会有警告mySubject.addObserver(observerA); // 不会重复添加

观察者模式与发布订阅模式有何不同?

这真的是一个老生常谈的问题,但它确实很重要,因为两者概念上很接近,但在实现和职责划分上有所区别。在我看来,最核心的区别在于它们之间是否存在一个“中间人”。观察者模式中,主题(Subject)是直接知道并管理着所有观察者(Observer)的。它维护一个观察者列表,并在状态改变时直接调用这些观察者的方法。这是一种“一对多”的直接依赖关系。就像一个明星(主题)直接管理着他的粉丝俱乐部(观察者),有新动态就直接发给所有粉丝。

而发布订阅模式(Pub/Sub)则引入了一个“事件中心”或“消息代理”(Broker/Event Bus)。发布者(Publisher)不直接知道订阅者(Subscriber),它只负责向事件中心发布消息;订阅者也不直接知道发布者,它只向事件中心订阅感兴趣的消息。所有的通信都通过这个中间人来完成。这就像出版社(发布者)把书交给书店(事件中心),读者(订阅者)去书店买书,出版社和读者之间并不直接打交道。

从解耦程度上看,发布订阅模式的解耦更彻底,因为它消除了发布者和订阅者之间的直接依赖。主题(发布者)和观察者(订阅者)之间完全互不干涉。这在大型应用中特别有用,可以避免组件之间形成复杂的网状依赖。观察者模式虽然也实现了观察者和主题的解耦(观察者不需要知道主题的具体实现,只需要知道它有

notify

方法),但主题本身还是需要管理观察者的列表,这种耦合是存在的。所以,选择哪种模式,往往取决于你对系统解耦程度的需求以及复杂性考量。

在哪些实际场景中,观察者模式能发挥作用?

观察者模式在前端开发中简直是无处不在,只是我们可能不总用“观察者模式”这个词来称呼它。最直观的例子就是DOM事件处理。当你在一个按钮上添加

addEventListener

监听点击事件时,这个按钮就是主题,你的回调函数就是观察者。按钮被点击时,它会通知所有注册的监听器。这不就是典型的观察者模式吗?

再比如,单页应用中的状态管理。虽然像Redux这样的库更多地被认为是发布订阅模式(因为它有一个中央的store作为事件中心),但其内部某些机制,比如组件订阅store的变化,然后根据变化重新渲染,这本质上也是一种观察行为。如果你自己实现一个简单的全局状态管理器,让组件注册监听某个状态的变化,那这就是观察者模式的典型应用。

千帆大模型平台 千帆大模型平台

面向企业开发者的一站式大模型开发及服务运行平台

千帆大模型平台 0 查看详情 千帆大模型平台

还有一些场景,比如:

实时数据更新: 假设你有一个图表组件,需要实时展示后端推送的数据。后端数据一更新,主题(数据服务)就通知图表组件(观察者)去刷新。UI组件间的通信: 当一个表单输入框的值改变时,可能需要另一个显示区域同步更新。输入框作为主题,显示区域作为观察者。游戏开发: 玩家角色的生命值、分数等属性变化时,可以通知UI显示、音效播放等观察者。

我觉得,只要是涉及到“当A发生变化时,B、C、D需要做出响应”这种需求,观察者模式就值得考虑。它提供了一种清晰、可维护的方式来处理这种一对多的依赖关系。

实现观察者模式时,有哪些常见的陷阱或优化考量?

实现观察者模式,虽然概念上简单,但在实际应用中还是有些细节需要注意,不然可能会引入一些问题。

一个比较常见的陷阱是内存泄漏。如果观察者没有被正确地从主题中移除,即使观察者本身已经不再被使用了(比如对应的DOM元素被移除了),主题仍然会持有对它的引用。这意味着垃圾回收器无法回收这个观察者,导致内存占用持续增加。这在单页应用中尤其常见,页面切换或者组件销毁时,忘记取消订阅是很要命的。所以,我的经验是,在组件生命周期结束时(比如React的

componentWillUnmount

useEffect

的返回函数中),一定要记得调用

removeObserver

另一个是通知的顺序和性能。如果有很多观察者,或者某个观察者的回调函数执行时间很长,同步通知可能会阻塞主线程,导致UI卡顿。这时可以考虑异步通知,比如使用

setTimeout

requestAnimationFrame

或者微任务(

Promise.resolve().then(...)

)来调度观察者的执行。这样可以把耗时操作放到事件循环的下一轮,避免阻塞。但异步通知也会带来额外的复杂性,比如如何确保通知的顺序,以及如何处理通知失败的情况。

再来就是错误处理。在我的示例代码里,我加了一个

try-catch

块来包裹观察者的执行。这是很重要的,因为如果一个观察者在执行时抛出了未捕获的错误,它可能会中断整个通知链,导致后续的观察者无法收到通知。捕获错误并记录下来,可以确保系统的健壮性。

最后,还有参数传递的考量。

notify

方法通常会传递一些数据给观察者。这些数据应该包含观察者所需的所有信息,但也要避免传递过大的对象,否则会增加内存开销和数据序列化的负担。有时候,一个简单的ID或者一个表示变化类型的枚举值就足够了,观察者可以根据这个ID再去主题那里拉取更详细的数据。这种“拉取”模式(Pull Model)与“推送”模式(Push Model)是观察者模式的两种变体,各有优缺点。推送模式简单直接,但可能传递冗余数据;拉取模式更灵活,但观察者需要主动获取数据。具体用哪种,得看实际需求。

以上就是JS如何实现观察者模式的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/339265.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月5日 17:35:39
下一篇 2025年11月5日 17:36:41

相关推荐

  • 币圈新手入门指南之学习资源推荐

    进入加密资产领域需系统学习,1. 基础知识可学习Binance Academy免费课程、CoinDesk 101专栏及Andreessen Horowitz研报;2. 实时资讯与数据推荐The Block数据仪表盘、Messari行情周报和CryptoPanic信息聚合;3. 技术分析工具首选Tra…

    2025年12月10日
    000
  • 元老级比特币(BTC)玩家“信心动摇”评论引发社区热议

    目录 抛售比特币背后存在”多种原因” 分析师强调比特币”人人可用” ‍一位加密市场观察者提出了不同看法,他表示:“每个人都将走向终点。在某个阶段,财富积累的意义会逐渐淡化。” 一位颇具影响力的加密货币评论员近日在社区中掀起波澜,他指出,随着机构资本持续…

    2025年12月10日
    000
  • 随机相对强弱指标(Stochastic RSI)的技术分析

    目录 什么是基本面分析?什么是技术分析?什么是滞后指标?什么是领先指标?理解随机RSI:RSI和随机RSI的区别:StochRSI 如何运作?如何解读 Stochastic RSI 指标?如何计算随机RSI?结语 随机相对强弱指标(stochastic rsi)是一种用于评估特定时间段内资产强弱状态…

    2025年12月10日 好文分享
    000
  • 什么是算法稳定币?其价格稳定机制如何?与传统稳定币的区别在哪里?

    1、算法稳定币通过供应调节、智能合约控制、代币激励和预言机数据实现价格锚定1美元的稳定机制;2、主要支持平台包括欧意OKX 、Binance必安、火必HTX和Gate.io大门,分别提供交易流动性与新兴项目入口;3、与传统稳定币相比,其抵押方式为算法而非法币储备,去中心化程度更高,稳定性受市场情绪影…

    2025年12月10日
    000
  • PCE调整指数是什么?PCE指数意义,PCE对加密市场的重要性

    目录 什么是PCE调整指数?核心PCE 是什么?为什么PCE调整指数重要?PCE调整指数是如何工作的?PCE调整指数与CPIPCE调整指数的局限性PCE 指数和CPI 指数有什么差别?PCE调整指数在加密市场中的作用如何跟踪PCE调整指数结论 理解pce及其调整指数对政策制定者、经济学家以及关注通胀…

    2025年12月10日
    000
  • 迷因币狂热:狗狗币、PEPE与加密预售热潮

    迷因币热度降温?揭秘为何投资者正转向blockchainfx与token6900等预售项目,寻找真正价值与高潜力回报。 迷因币生态始终处于快速更迭之中。虽然狗狗币(Dogecoin, DOGE)和PEPE曾掀起热潮,如今越来越多资金开始流向加密货币预售市场,押注那些具备实际功能和长期前景的新项目。以…

    2025年12月10日
    000
  • 比特币和XRP的核心差异在哪?哪个更适合长期持有?XRP会逆袭吗?

    数字资产领域存在众多项目,比特币与xrp是其中备受关注的两种。它们各自拥有独特的设计哲学、技术特点与应用场景,因此在比较强弱和投资价值时,需要从多个维度进行审视。xrp是否有可能取代比特币,则是一个涉及其核心功能与市场定位的问题。 比特币的本质与市场地位 1. 比特币作为第一种去中心化数字货币,于2…

    2025年12月10日
    000
  • 稳定币USDT、USDC、DAI 有何区别?如何选择?

    稳定币是币圈的重要资产锚点,通常与美元等法币1:1挂钩,能帮助用户在市场波动时规避风险。目前主流的稳定币包括 usdt、usdc 和 dai,它们在原理、安全性与应用场景上各有不同。 三种稳定币的主要区别 USDT(Tether):由 Tether 公司发行,是目前市场占比最高的稳定币。它由中心化公…

    2025年12月10日
    000
  • 未来五年内(2025-2030)狗狗币的价值上限可能性有多大?

    随着加密货币市场日趋成熟,狗狗币(doge)作为具有强社区基础和广泛传播力的加密资产,其未来五年的表现备受关注。本文将分析狗狗币在2025至2030年间可能达到的价值上限,并从技术支持、市场情绪、平台支持等维度进行评估,帮助投资者理性判断其潜力。 一、狗狗币未来价值上限预测 1美元关口 这是多数持币…

    2025年12月10日
    000
  • HTX(火必网)交易手续费是多少_费率标准及优惠介绍

    HTX(火必网)交易手续费是多少_费率标准及优惠介绍 一、HTX平台基础手续费标准 htx(原火必网)采用挂单(maker)与吃单(taker)双费率结构,默认费率如下: 币币交易挂单:0.2%币币交易吃单:0.2%合约交易手续费:按不同杠杆与合约类型动态设定,约为 0.02%–0.04% 火币官方…

    好文分享 2025年12月10日
    000
  • 山寨币热门讨论社区和社交平台推荐

    山寨币热门讨论社区和社交平台推荐 一、币圈山寨币社区的重要性 山寨币市场活跃度与社区氛围密切相关,活跃的讨论社区不仅能提供最新项目动态和技术分析,还能帮助投资者及时捕捉交易机会和风险信号。通过专业社群和社交平台的交流,投资者能够获取多角度信息,提升决策效率和准确性。 Binance币安 官网直达: …

    2025年12月10日
    000
  • 山寨币如何通过社交媒体推广项目?

    山寨币如何通过社交媒体推广项目? 一、社交媒体在山寨币推广中的作用 社交媒体作为信息传播的重要渠道,具备快速覆盖广泛用户和互动性强的特点,成为山寨币项目宣传和社区建设的关键平台。合理运用社交媒体,有助于提升项目知名度和用户黏性。 Binance币安 官网直达: 安卓安装包下载: 欧易OKX ️ 官网…

    2025年12月10日
    000
  • PEPE币最新k线走势图app PEPE24小时价格动态实时分析

    想要精准把握PEPE币的每一次价格脉动,抓住每一个潜在的投资良机吗?在这个瞬息万变的数字货币世界里,一款专业且高效的K线走势图APP是您不可或缺的制胜利器。它不仅能帮助您实时洞察PEPE币的24小时价格动态,更能提供深度分析工具,助您在复杂的市场环境中做出更明智的投资决策,抢占先机。 本文为您准备了…

    2025年12月10日
    000
  • 什么是加密货币?它和数字货币一样吗?

    很多新手一开始接触币圈时都会有疑问:“加密货币”和“数字货币”到底是不是一回事?其实,两者虽然都以数字形式存在,但本质和用途有明显区别。 加密货币是什么? 加密货币是基于区块链技术发行的虚拟资产,例如比特币(BTC)、以太坊(ETH)等。它们利用密码学技术确保交易安全,并且去中心化、不依赖银行或政府…

    2025年12月10日
    000
  • 山姆大叔的比特币储备:美国政府持有比特币是怎么回事?

    你有没有想过,美国政府到底持有多少比特币?事实可能比你想象的要复杂得多,其中被扣押和被没收资产之间的区别起着关键作用。 美国政府与比特币的关系已成为热议话题,尤其是在讨论其持币规模时。政府是否秘密地“囤积”了一大笔比特币宝藏,还是事情远没有这么简单?让我们一起来看看山姆大叔(Uncle Sam)比特…

    2025年12月10日
    000
  • 稳定币和法币有什么区别_是否可以代替现金?

    稳定币和法币有什么区别_是否可以代替现金? 一、什么是稳定币? 稳定币(stablecoin)是一种与现实世界资产(如美元、欧元等法币)挂钩的加密货币。其目标是维持币值的稳定,常见的稳定币包括 usdt、usdc、dai 等。 Binance币安 官网直达: 安卓安装包下载: 欧易OKX ️ 官网直…

    2025年12月10日
    000
  • 新币PQRS项目团队背景深度调研_值得投资吗?

    新币PQRS项目团队背景深度调研_值得投资吗? 一、团队信息透明度 未在官网或白皮书中找到核心团队成员的实名与履历。No public GitHub repo under pqrs-org 展示经验证的项目开发活动,仅为网站托管仓库,无法反映区块链开发进展。:contentReference[oai…

    2025年12月10日
    000
  • Luna (LUNA) 和 Luna Classic (LUNC) 有什么不同,哪个更值得投资

    Luna (LUNA) 和 Luna Classic (LUNC) 是两种截然不同的数字资产,主要区别在于1.运行的区块链不同:LUNC是原始Terra区块链的代币,现更名为Terra Classic;LUNA则是新创建的Terra 2.0链上的原生代币。2.设计初衷不同:LUNC曾作为算法稳定币U…

    2025年12月10日
    000
  • XRP 瑞波币达到 3 美元后会继续上涨吗?

    XRP近期突破3美元是市场关注焦点。1. XRP本周从2.36美元低点反弹,最高触及3美元后回落至2.95美元,周涨幅达26.5%;2. 3美元是历史压力位,早期持有者可能抛售解套,形成阻力;3. 当前机构资金深度参与,通过ETF等渠道提供更强支撑,或助其突破前高。投资者需密切关注3美元关口表现,决…

    2025年12月10日
    000
  • php怎么连接mysql数据库_php使用mysqli连接数据库

    PHP连接MySQL推荐使用mysqli扩展,因其支持预处理语句、提供面向对象和过程两种接口、具备更高安全性和性能,且兼容MySQL新特性,而旧的mysql扩展已被废弃。 好的,PHP要连接MySQL数据库,现在主流且推荐的方式就是用 mysqli 扩展。它比老旧的 mysql 扩展更安全、功能也更…

    2025年12月10日
    000

发表回复

登录后才能评论
关注微信