JavaScript实现与使用发布/订阅模式详解
什么是发布/订阅模式?
发布/订阅模式(Publish/Subscribe Pattern)是一种在软件设计中广泛使用的模式,它将一个系统的组件分为两类:发布者(Publisher)和订阅者(Subscriber)。发布者负责发布事件(消息),订阅者通过注册事件来接收消息。
发布/订阅模式的应用场景
- 客户端与服务端的数据交互
- 一对多的通信,例如:聊天室、广播
- 客户端GUI事件
发布/订阅模式的优点
- 实现了订阅者和发布者的解耦
- 可以精确控制订阅者处理什么事件
- 支持一对多的事件处理
实现JavaScript发布/订阅模式
下面我们详细讲解如何使用JavaScript实现发布/订阅模式:
- 首先我们需要创建一个 PubSub 对象,该对象是我们发布/订阅模式的核心部分。
const PubSub = {
subscribe(event, callback) {
if (!this[event]) {
this[event] = []
}
this[event].push(callback)
},
publish(event, data) {
if (!this[event]) {
return
}
this[event].forEach((callback) => callback(data))
},
unsubscribe(event, callback) {
if (!this[event]) {
return
}
this[event] = this[event].filter((cb) => cb !== callback)
},
}
- 创建一个 Publisher 对象,该对象负责发布事件。
const Publisher = {
publishEvent() {
PubSub.publish('anEvent', { event: 'anEvent', data: '传递的数据' })
},
}
- 创建一个 Subscriber 对象,该对象负责订阅事件。
const Subscriber1 = {
callback(data) {
console.log('Subscriber1 订阅到了事件:', data)
}
}
const Subscriber2 = {
callback(data) {
console.log('Subscriber2 订阅到了事件:', data)
}
}
PubSub.subscribe('anEvent', Subscriber1.callback)
PubSub.subscribe('anEvent', Subscriber2.callback)
- 最后,我们来测试一下上面的代码是否能够正常工作。
Publisher.publishEvent()
// 输出:
// Subscriber1 订阅到了事件: {event: "anEvent", data: "传递的数据"}
// Subscriber2 订阅到了事件: {event: "anEvent", data: "传递的数据"}
示例说明
下面我们通过两个示例来说明发布/订阅模式的使用。
示例1:购物车计算器
我们来编写一个购物车计算器,当我们添加或删除商品时,自动计算当前购物车的总价。
const ShoppingCart = {
products: [],
addProduct(product) {
this.products.push(product)
PubSub.publish('onCartUpdated', this.products)
},
removeProduct(productId) {
this.products = this.products.filter((product) => product.id !== productId)
PubSub.publish('onCartUpdated', this.products)
}
}
const Total = {
update(cart) {
console.log('购物车价格更新了:', this.calculateTotal(cart))
},
calculateTotal(cart) {
return cart.reduce((total, product) => total + product.price, 0)
},
}
PubSub.subscribe('onCartUpdated', Total.update.bind(Total))
ShoppingCart.addProduct({ id: 1, price: 10 })
// 输出:购物车价格更新了: 10
ShoppingCart.addProduct({ id: 2, price: 5 })
// 输出:购物车价格更新了: 15
ShoppingCart.removeProduct(2)
// 输出:购物车价格更新了: 10
在上面的代码示例中,当我们添加或删除商品时,就会发出名为 onCartUpdated 的事件,Total 对象订阅了这个事件并且会在每次收到该事件时通过调用 Total.update()
方法来更新购物车价格。
示例2:事件总线
前端应用程序通常需要处理多个组件之间的通信,例如:我们需要在不同的组件之间共享数据或触发某些操作。这就需要使用到一个简单的事件总线来解决这个问题。
const EventBus = {
events: {},
on(event, callback) {
if (!this.events[event]) {
this.events[event] = []
}
this.events[event].push(callback)
},
off(event, callback) {
if (!this.events[event]) {
return
}
this.events[event] = this.events[event].filter((cb) => cb !== callback)
},
emit(event, data) {
if (!this.events[event]) {
return
}
this.events[event].forEach((callback) => callback(data))
},
}
const ComponentA = {
created() {
EventBus.on('componentB:clicked', this.updateData.bind(this))
},
updateData(data) {
console.log('ComponentA 发现 componentB 被点击了:', data)
},
}
const ComponentB = {
clicked() {
EventBus.emit('componentB:clicked', { text: '这是 componentB 发布的事件' })
},
}
ComponentA.created()
ComponentB.clicked()
// 输出:ComponentA 发现 componentB 被点击了: {text: "这是 componentB 发布的事件"}
在上面的示例中,当 ComponentB 触发了点击事件,它就会发布一个名为 componentB:clicked 的事件,并将数据传递给所有订阅该事件的组件。我们通过使用 EventBus.on()
以及 EventBus.emit()
来维护订阅和发布行为。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript实现与使用发布/订阅模式详解 - Python技术站