我的编程空间,编程开发者的网络收藏夹
学习永远不晚

深入了解JavaScript发布订阅模式

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

深入了解JavaScript发布订阅模式

JavaScript 发布订阅模式(Publish/Subscribe Pattern)是一种常用的设计模式。在发布订阅模式中,事件的发生者(发布者)不需要直接调用事件的处理者(订阅者),而是通过一个「发布-订阅中心」来管理事件的发生和处理。具体来说,发布者将事件发布到「发布-订阅中心」中,订阅者可以向「发布-订阅中心」注册事件处理函数,当事件发生时,「发布-订阅中心」会将事件通知给所有注册了该事件处理函数的订阅者,订阅者就可以处理该事件了。

发布订阅模式的核心思想是解耦事件的发生和事件的处理,使得事件发生者和事件处理者之间不直接依赖,从而提高程序的灵活性和可维护性。使用发布订阅模式可以将事件的发生和处理分开,使得不同的订阅者可以独立处理事件,同时也可以动态地添加或删除订阅者,满足不同的业务需求。

本文将介绍 JavaScript 发布订阅模式的基本原理、应用场景以及各场景的代码示例。

发布订阅模式的基本原理

JavaScript 发布订阅模式的基本原理是:有一个主题对象,该对象维护一个订阅者列表,当主题对象发生变化时,主题对象会遍历订阅者列表,调用每个订阅者的更新方法,通知订阅者进行相应的处理。

在 JavaScript 中,可以通过自定义事件和回调函数实现发布订阅模式。主题对象维护一个事件列表,每个事件对应一个或多个回调函数。当主题对象发生变化时,主题对象会触发相应的事件,调用该事件对应的所有回调函数,通知订阅者进行相应的处理。

// 消息代理
class MessageBroker {
  constructor() {
    this.subscriptions = {};
  }

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

  publish(topic, data) {
    if (!this.subscriptions[topic]) {
      return;
    }
    this.subscriptions[topic].forEach((callback) => {
      callback(data);
    });
  }
}

// 发布者
class Publisher {
  constructor(broker) {
    this.broker = broker;
  }

  publishMessage(topic, message) {
    this.broker.publish(topic, message);
  }
}

// 订阅者
class Subscriber {
  constructor(broker, name) {
    this.broker = broker;
    this.name = name;
  }

  subscribeToTopic(topic) {
    this.broker.subscribe(topic, (data) => {
      console.log(`Subscriber ${this.name} received message: ${data}`);
    });
  }
}

// 使用示例
const broker = new MessageBroker();
const publisher = new Publisher(broker);

const subscriber1 = new Subscriber(broker, 'Alice');
const subscriber2 = new Subscriber(broker, 'Bob');

subscriber1.subscribeToTopic('news');
subscriber2.subscribeToTopic('weather');

publisher.publishMessage('news', 'Breaking news: the sky is blue');
publisher.publishMessage('weather', 'It will be sunny tomorrow');

发布订阅模式和观察者模式的区别

发布订阅模式(Publish/Subscribe Pattern)和观察者模式(Observer Pattern)都是常用的设计模式,它们都是用于处理对象之间的依赖关系和通信。虽然它们的实现方式和应用场景有些类似,但是它们之间还是存在一些区别的。

 

对象关系

观察者模式中,被观察者和观察者之间的关系是一对多的关系,即一个被观察者可以有多个观察者,但是每个观察者只关注一个被观察者。被观察者维护一个观察者列表,当被观察者发生变化时,通知所有观察者进行相应的处理。

发布订阅模式中,发布者和订阅者之间的关系是多对多的关系,即一个发布者可以有多个订阅者,每个订阅者可以关注多个发布者。发布者和订阅者之间通过「发布-订阅中心」进行通信,当发布者发生变化时,通知所有订阅者进行相应的处理。

解耦

在观察者模式中,被观察者和观察者之间的通信是直接的,即被观察者会直接调用观察者的方法进行通信。这种直接的通信方式可能会导致被观察者与观察者之间的耦合度较高。

在发布订阅模式中,发布者和订阅者之间的通信是通过「发布-订阅中心」进行的,即发布者不直接与订阅者通信,而是通过「发布-订阅中心」进行通信。这种间接的通信方式可以降低发布者与订阅者之间的耦合度。

发布订阅模式的应用场景

下面我们来举几个常见的发布订阅模式的应用场景和代码示例。

生产者 & 消费者关系

发布订阅模式适用于需要解耦生产者和消费者之间关系的场景,生产者只需要发布消息,而不需要关心哪些消费者会收到消息。消费者可以订阅自己感兴趣的主题,只有在该主题上有新的消息时才会收到通知。这样可以提高代码的灵活性和可维护性。

以下是一个基于发布订阅模式的具体场景和代码示例:

假设我们正在开发一个在线商城,需要实时更新商品价格和库存信息。我们可以使用发布订阅模式,在商品库存和价格发生变化时,自动向所有关注该商品的客户端推送更新。

// 消息代理
class MessageBroker {
  constructor() {
    this.subscriptions = {};
  }

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

  publish(topic, data) {
    if (!this.subscriptions[topic]) {
      return;
    }
    this.subscriptions[topic].forEach((callback) => {
      callback(data);
    });
  }
}

// 商品类
class Product {
  constructor(name, price, stock) {
    this.name = name;
    this.price = price;
    this.stock = stock;
  }

  setPrice(newPrice) {
    this.price = newPrice;
    this.broker.publish(`product/${this.name}/price`, this.price);
  }

  setStock(newStock) {
    this.stock = newStock;
    this.broker.publish(`product/${this.name}/stock`, this.stock);
  }

  setBroker(broker) {
    this.broker = broker;
  }
}

// 客户端类
class Client {
  constructor(name) {
    this.name = name;
  }

  subscribeToProduct(product) {
    product.broker.subscribe(`product/${product.name}/price`, (data) => {
      console.log(`Client ${this.name} received new price for ${product.name}: ${data}`);
    });
    product.broker.subscribe(`product/${product.name}/stock`, (data) => {
      console.log(`Client ${this.name} received new stock for ${product.name}: ${data}`);
    });
  }
}

// 使用示例
const broker = new MessageBroker();

const product1 = new Product('Product 1', 100, 10);
const product2 = new Product('Product 2', 200, 20);

product1.setBroker(broker);
product2.setBroker(broker);

const client1 = new Client('Alice');
const client2 = new Client('Bob');

client1.subscribeToProduct(product1);
client2.subscribeToProduct(product2);

product1.setPrice(120);
product1.setStock(5);

product2.setPrice(180);
product2.setStock(10);

在上面的示例中,我们创建了一个消息代理 MessageBroker,以及两个商品 Product 和两个客户端 Client。商品类中的 setPrice 和 setStock 方法会在价格和库存发生变化时向代理发送消息,客户端类中的 subscribeToProduct 方法会订阅指定商品的价格和库存主题,并在收到消息时打印出来。在这个示例中,我们使用 console.log 来模拟消息的输出。

消息队列

以下是一个简单的消息队列场景的代码示例,实现了消息的生产和消费:

class MessageQueue {
  constructor() {
    this.subscriptions = {};
    this.queue = [];
  }

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

  publish(topic, data) {
    if (!this.subscriptions[topic]) {
      return;
    }
    this.subscriptions[topic].forEach((callback) => {
      callback(data);
    });
  }

  enqueue(message) {
    this.queue.push(message);
  }

  dequeue() {
    return this.queue.shift();
  }

  process() {
    const message = this.dequeue();
    if (message) {
      this.publish(message.topic, message.data);
    }
  }
}

// 生产者
const producer = (queue) => {
  setInterval(() => {
    const message = { topic: 'test', data: new Date().toISOString() };
    queue.enqueue(message);
    console.log(`Produced message: ${JSON.stringify(message)}`);
  }, 1000);
};

// 消费者
const consumer = (queue) => {
  setInterval(() => {
    queue.process();
  }, 500);
};

// 使用示例
const queue = new MessageQueue();

queue.subscribe('test', (data) => {
  console.log(`Consumed message: ${data}`);
});

producer(queue);
consumer(queue);

在上面的代码示例中,我们定义了一个 MessageQueue 类,实现了基本的消息队列功能,包括订阅、发布、入队、出队和处理。生产者通过调用 enqueue 方法将消息入队,消费者通过调用 process 方法从队列中取出消息并进行处理。在使用示例中,我们创建了一个消息队列,生产者每隔一秒钟向队列中添加一个消息,消息的内容是当前时间。消费者每隔半秒钟从队列中取出一个消息并输出到控制台。

当我们运行上面的代码示例时,可以看到生产者不断地向队列中添加消息,消费者不断地从队列中取出消息并输出到控制台,实现了一个基本的消息队列。

自定义事件系统

在一些大型的 Web 应用中,可能需要实现自定义的事件系统,以便进行组件间通信和数据交互。这时可以使用 JavaScript 发布订阅模式,将「发布-订阅中心」作为主题对象,将事件监听器作为订阅者,实现自定义事件系统。

示例代码:

class EventEmitter {
  constructor() {
    this.events = {};
  }

  on(event, listener) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(listener);
  }

  off(event, listener) {
    if (!this.events[event]) {
      return;
    }
    const index = this.events[event].indexOf(listener);
    if (index >= 0) {
      this.events[event].splice(index, 1);
    }
  }

  emit(event, ...args) {
    if (!this.events[event]) {
      return;
    }
    this.events[event].forEach((listener) => {
      listener.apply(this, args);
    });
  }
}

// 使用示例
const emitter = new EventEmitter();

const listener1 = (msg) => {
  console.log(`Listener 1 received: ${msg}`);
};

const listener2 = (msg) => {
  console.log(`Listener 2 received: ${msg}`);
};

emitter.on('test', listener1);
emitter.on('test', listener2);

emitter.emit('test', 'test message 1');
// Output:
// Listener 1 received: test message 1
// Listener 2 received: test message 1

emitter.off('test', listener1);

emitter.emit('test', 'test message 2');
// Output:
// Listener 2 received: test message 2

结语

本文介绍了 JavaScript 发布订阅模式的基本原理、应用场景以及各场景的代码示例。在实际开发中,发布订阅模式可以用于解耦对象之间的依赖关系,提高代码的可维护性和可扩展性。不同的实现方式适用于不同的场景和框架,开发者可以根据需要选择合适的实现方式。同时,使用发布订阅模式也需要注意防止事件泄漏和内存泄漏等问题,保证代码的性能和稳定性。希望本文能够帮助读者更深入地了解 JavaScript 发布订阅模式,提高代码的质量和效率。

以上就是深入了解JavaScript发布订阅模式的详细内容,更多关于JavaScript 发布订阅模式的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

深入了解JavaScript发布订阅模式

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

深入了解JavaScript发布订阅模式

JavaScript 发布订阅模式(Publish/Subscribe Pattern)是一种常用的设计模式,发布订阅模式的核心思想是解耦事件的发生和事件的处理,本文将介绍 JavaScript 发布订阅模式的基本原理、应用场景以及各场景的代码示例,需要的朋友可以参考下
2023-05-19

Javascript设计模式之发布订阅模式

发布---订阅模式又叫观察者模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知
2022-12-19

node.js 发布订阅模式的实例

实例如下://导入内置模块 let EventEmitter = require('events'); let util=require('util'); //Man继承EventEmitter util.inherits(Man,Even
2022-06-04

JavaScript 简单实现观察者模式和发布-订阅模式

JavaScript 简单实现观察者模式和发布-订阅模式 1. 观察者模式1.1 什么是观察者模式1.2 代码实现 2. 发布-订阅模式2.1 什么是发布-订阅模式2.2 代码实现2.2.1 基础版2.2.2 取消订阅2.2.3
2023-08-21

Redis发布/订阅模式实例分析

这篇文章主要讲解了“Redis发布/订阅模式实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Redis发布/订阅模式实例分析”吧!Redis发布/订阅应用发布订阅(pub/sub)是一
2023-06-27

JS前端设计模式之发布订阅模式详解

这篇文章主要为大家介绍了JS前端设计模式之发布订阅模式详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

spring发布订阅模式怎么实现

在Spring中,可以使用Spring的事件机制来实现发布订阅模式。创建事件对象:首先,需要创建一个事件对象,该对象包含了需要发布的数据。public class CustomEvent extends ApplicationEvent {
spring发布订阅模式怎么实现
2024-02-29

每天一个设计模式之订阅-发布模式

博主按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript(_靠这吃饭_)和python(_纯粹喜欢_)两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :)0. 项目地址每天一
2023-01-31

JavaScript利用发布订阅模式编写事件监听函数

发布订阅是一种设计模式,EventHub可以被看作是一种Pub/Sub实现。本文就来讲讲如何利用eventHub发布订阅写一个事件监听函数,感兴趣的可以了解一下
2023-05-15

Redis发布/订阅模式是怎么工作的

Redis发布/订阅模式是一种消息传递模式,其中发布者向频道发布消息,而订阅者则订阅感兴趣的频道以接收消息。以下是Redis发布/订阅模式的工作原理:发布者(Publisher)使用PUBLISH命令向指定频道(Channel)发布消息。
Redis发布/订阅模式是怎么工作的
2024-05-07

如何用JS写一个发布订阅模式

这篇文章给大家介绍如何用JS写一个发布订阅模式,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。什么是发布订阅模式?能手写实现一下吗?它和观察者模式有区别吗?...1 场景引入我们先来看这么一个场景:假设现在有一个社交平台
2023-06-25

SpringBoot Redis发布订阅模式的方法是什么

本篇内容主要讲解“SpringBoot Redis发布订阅模式的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringBoot Redis发布订阅模式的方法是什么”吧!注意:red
2023-06-22

JavaScript怎么利用发布订阅模式编写事件监听函数

这篇“JavaScript怎么利用发布订阅模式编写事件监听函数”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“JavaScri
2023-07-06

Redis发布/订阅模式的应用场景有哪些

实时通知:可以用于实时通知系统,例如实时更新新闻、股票行情、天气预报等信息。聊天室:可以用于实现即时聊天室功能,用户发送消息时,消息会被发布到相应的频道,其他订阅了该频道的用户会收到消息。实时数据更新:可以用于实现实时数据更新功能,当数
Redis发布/订阅模式的应用场景有哪些
2024-05-07

编程热搜

目录