JS中发布/订阅模式的简单应用

简介: JS中发布/订阅模式的简单应用

深入理解JavaScript中的发布/订阅模式

在现代的前端开发中,我们经常会遇到需要多个组件或模块间进行通信的情况。为了解耦这些组件,使它们之间的依赖关系降到最低,并实现更加灵活和可维护的代码,我们经常会使用一些设计模式。其中,发布/订阅模式(也被称为观察者模式)是一种非常常见且有用的模式。

什么是发布/订阅模式?

发布/订阅模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,它的所有依赖者(订阅者)都会自动收到通知并更新。

在个模式的好处自安于能够对代码进行解耦,实现了“高内聚,低耦合”的理念。

1.建立一个事件总线。

2.发布事件。

3.订阅事件。

//事件总线,管理事件
class Notcice {
    #arr = new Map()
    constructor() {

    }
    add(str, fn) {
        if (this.#arr.has(str)) {
            this.#arr.set(str, fn)
        } else {
            throw new Error("这个事件已经被注册了")
        }

    }
    emit(str, params) {
        if (this.#arr.has(str)) {
            this.#arr.get(str)(params);
        } else {
            throw new Error("别TM瞎掉")
        }
    }
}
//new 一个实例,并且一直用这个实例,保证我们的只有一个总线
let myNotice = new Notcice()
//发布一个eat事件
myNotice.add("eat", (params) => {
    console.log(`吃${params}`);
})
//订阅
myNotice.emit("eat", "苹果")

发布者(Publisher)

发布者是可以发送消息的对象,它们维护了一个或多个订阅者的列表,并在适当的时候通知它们。

订阅者(Subscriber)

订阅者是对特定事件感兴趣的对象,它们将自己注册到发布者上,以便在事件发生时接收通知。

事件(Event)

事件是发布者向订阅者发送的消息或通知。

JavaScript中的实现

在JavaScript中,我们可以使用原生的对象和数组来实现发布/订阅模式。下面是一个简单的例子:

class PubSub {
  constructor() {
    this.subscribers = {};
  }

  subscribe(event, callback) {
    if (!this.subscribers[event]) {
      this.subscribers[event] = [];
    }
    this.subscribers[event].push(callback);
  }

  publish(event, data) {
    if (this.subscribers[event]) {
      this.subscribers[event].forEach(callback => callback(data));
    }
  }
}

// 使用
const pubSub = new PubSub();

// 订阅者1
pubSub.subscribe('message', (data) => {
  console.log('订阅者1收到消息:', data);
});

// 订阅者2
pubSub.subscribe('message', (data) => {
  console.log('订阅者2收到消息:', data);
});

// 发布者发布消息
pubSub.publish('message', 'Hello, World!');

在这个例子中,我们创建了一个PubSub类,它有两个主要的方法:subscribepublishsubscribe方法用于注册事件和对应的回调函数,而publish方法用于发布事件并传递数据给所有订阅了该事件的回调函数。

应用场景

发布/订阅模式在前端开发中有着广泛的应用,下面列举了几个常见的场景:

1. 自定义事件

在复杂的单页应用(SPA)中,组件之间的通信经常需要跨越多个层级。使用发布/订阅模式,我们可以创建自定义事件,让组件在需要的时候触发这些事件,而其他组件可以订阅这些事件并在事件发生时执行相应的逻辑。

2. 状态管理

在前端状态管理库(如Redux、Vuex)中,发布/订阅模式是实现状态更新的核心机制。当状态发生变化时,所有订阅了该状态的组件都会收到通知并重新渲染。

3. 异步编程

在异步编程中,发布/订阅模式可以帮助我们解耦异步操作和它们的回调函数。例如,我们可以使用Promise或async/await语法来订阅一个异步操作的结果,并在操作完成时执行相应的逻辑。

4. 插件系统

在插件系统中,发布/订阅模式可以让插件之间以解耦的方式进行通信。插件可以订阅系统事件,并在事件发生时执行相应的操作,从而实现插件之间的协作和扩展。

注意事项

虽然发布/订阅模式非常有用,但在使用时也需要注意一些问题:

1. 内存泄漏

如果订阅者不再需要接收某个事件的消息,但没有取消订阅,那么当该事件再次发生时,订阅者的回调函数仍然会被执行。这可能会导致内存泄漏和不必要的计算。因此,我们需要在适当的时候取消订阅。

2. 事件命名冲突

如果不同的发布者发布了同名的事件,或者订阅者订阅了多个同名的事件,那么可能会发生事件命名冲突。为了避免这种情况,我们可以使用命名空间或唯一标识符来区分不同的事件。

3. 回调函数的执行顺序

在发布事件时,订阅者的回调函数是按照它们被注册的顺序依次执行的。如果回调函数的执行顺序很重要,我们需要确保它们按照正确的顺序注册。

结论

发布/订阅模式是一种非常强大且灵活的设计模式,它可以帮助我们解耦组件、降低依赖关系,并实现更加可维护和可扩展的代码。在前端开发中,我们可以利用JavaScript的原生特性来实现这种模式,并应用于自定义事件、状态管理、异步编程和插件系统等场景。但在使用时,我们也需要注意内存泄漏、事件命名冲突和回调函数的执行顺序等问题。通过合理地运用发布/订阅模式,我们可以编写出更加优雅和高效的前端代码。


是不是很简单啊?喜欢的小伙伴留言点赞关注吧!

相关文章
|
2月前
|
前端开发 机器人 API
前端大模型入门(一):用 js+langchain 构建基于 LLM 的应用
本文介绍了大语言模型(LLM)的HTTP API流式调用机制及其在前端的实现方法。通过流式调用,服务器可以逐步发送生成的文本内容,前端则实时处理并展示这些数据块,从而提升用户体验和实时性。文章详细讲解了如何使用`fetch`发起流式请求、处理响应流数据、逐步更新界面、处理中断和错误,以及优化用户交互。流式调用特别适用于聊天机器人、搜索建议等应用场景,能够显著减少用户的等待时间,增强交互性。
358 2
|
2月前
|
JavaScript 前端开发 API
探索后端技术:Node.js的优势和实际应用
【10月更文挑战第6天】 在当今数字化时代,后端开发是任何成功软件应用的关键组成部分。本文将深入探讨一种流行的后端技术——Node.js,通过分析其核心优势和实际应用案例,揭示其在现代软件开发中的重要性和潜力。
138 2
|
9天前
|
存储 缓存 JavaScript
如何优化Node.js应用的内存使用以提高性能?
通过以上多种方法的综合运用,可以有效地优化 Node.js 应用的内存使用,提高性能,提升用户体验。同时,不断关注内存管理的最新技术和最佳实践,持续改进应用的性能表现。
|
29天前
|
数据可视化 JavaScript 前端开发
数据可视化进阶:D3.js在复杂数据可视化中的应用
【10月更文挑战第26天】数据可视化是将数据以图形、图表等形式呈现的过程,帮助我们理解数据和揭示趋势。D3.js(Data-Driven Documents)是一个基于JavaScript的库,使用HTML、SVG和CSS创建动态、交互式的数据可视化。它通过数据驱动文档的方式,将数据与DOM元素关联,提供高度的灵活性和定制性,适用于复杂数据的可视化任务。 示例代码展示了如何使用D3.js创建一个简单的柱状图,展示了其基本用法。D3.js的链式调用和回调函数机制使代码简洁易懂,支持复杂的布局和交互逻辑。
67 3
|
2月前
|
机器学习/深度学习 自然语言处理 JavaScript
信息论、机器学习的核心概念:熵、KL散度、JS散度和Renyi散度的深度解析及应用
在信息论、机器学习和统计学领域中,KL散度(Kullback-Leibler散度)是量化概率分布差异的关键概念。本文深入探讨了KL散度及其相关概念,包括Jensen-Shannon散度和Renyi散度。KL散度用于衡量两个概率分布之间的差异,而Jensen-Shannon散度则提供了一种对称的度量方式。Renyi散度通过可调参数α,提供了更灵活的散度度量。这些概念不仅在理论研究中至关重要,在实际应用中也广泛用于数据压缩、变分自编码器、强化学习等领域。通过分析电子商务中的数据漂移实例,展示了这些散度指标在捕捉数据分布变化方面的独特优势,为企业提供了数据驱动的决策支持。
84 2
信息论、机器学习的核心概念:熵、KL散度、JS散度和Renyi散度的深度解析及应用
|
2月前
|
前端开发 JavaScript UED
探索JavaScript中的异步编程模式
【10月更文挑战第21天】在数字时代的浪潮中,JavaScript作为一门动态的、解释型的编程语言,以其卓越的灵活性和强大的功能在Web开发领域扮演着举足轻重的角色。本篇文章旨在深入探讨JavaScript中的异步编程模式,揭示其背后的原理和实践方法。通过分析回调函数、Promise对象以及async/await语法糖等关键技术点,我们将一同揭开JavaScript异步编程的神秘面纱,领略其带来的非阻塞I/O操作的魅力。让我们跟随代码的步伐,开启一场关于时间、性能与用户体验的奇妙之旅。
|
2月前
|
JavaScript 前端开发 开发者
探索JavaScript原型链:深入理解与实战应用
【10月更文挑战第21天】探索JavaScript原型链:深入理解与实战应用
32 1
|
22天前
|
前端开发 JavaScript UED
探索JavaScript的异步编程模式
【10月更文挑战第33天】在JavaScript的世界里,异步编程是提升应用性能和用户体验的关键。本文将带你深入理解异步编程的核心概念,并展示如何在实际开发中运用这些知识来构建更流畅、响应更快的Web应用程序。从回调函数到Promises,再到async/await,我们将一步步解锁JavaScript异步编程的秘密,让你轻松应对各种复杂的异步场景。
|
2月前
|
JavaScript 前端开发 API
Vue.js:打造高效前端应用的最佳选择
【10月更文挑战第9天】Vue.js:打造高效前端应用的最佳选择
21 2
|
2月前
|
设计模式 JavaScript 前端开发
探索JavaScript中的闭包:从基础概念到实际应用
在本文中,我们将深入探讨JavaScript中的一个重要概念——闭包。闭包是一种强大的编程工具,它允许函数记住并访问其所在作用域的变量,即使该函数在其作用域之外被调用。通过详细解析闭包的定义、创建方法以及实际应用场景,本文旨在帮助读者不仅理解闭包的理论概念,还能在实际开发中灵活运用这一技巧。