马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
在前端开辟中,发布订阅是一种常见的开辟场景,允许一个对象(发布者)发布变乱,而多个对象(订阅者)可以订阅并吸取这些变乱。
发布订阅在设计模式中,可以理解为 观察者模式 / Observer Pattern
一、常见实现方案
以下是一些常见的实现方案:
1.1 使用变乱发射器(Event Emitter)
许多 JavaScript 框架和库内置了变乱发射器机制,例如 Node.js 的 EventEmitter 类。
- const EventEmitter = require('events');
- const eventEmitter = new EventEmitter();
- // 定义事件
- eventEmitter.on('event', (data) => {
- console.log('Event received:', data);
- });
- // 触发事件
- eventEmitter.emit('event', 'Hello World!');
复制代码 1.2 自定义变乱系统(EventBus)
本身实现一个简单的发布订阅系统,可以通过维护一个变乱监听器的映射表来实现。
- class EventBus {
- constructor() {
- this.listeners = {};
- }
- on(event, listener) {
- if (!this.listeners[event]) {
- this.listeners[event] = [];
- }
- this.listeners[event].push(listener);
- }
- emit(event, data) {
- if (this.listeners[event]) {
- this.listeners[event].forEach(listener => listener(data));
- }
- }
- off(event, listener) {
- if (this.listeners[event]) {
- this.listeners[event] = this.listeners[event].filter(l => l !== listener);
- }
- }
- }
- const eventBus = new EventBus();
- eventBus.on('message', (data) => console.log('Message received:', data));
- eventBus.emit('message', 'Hello EventBus!');
复制代码 1.3 使用库如 PubSubJS
PubSubJS 是一个轻量级的 JavaScript 发布订阅库。
- const PubSub = require('pubsub-js');
- // 订阅
- const token = PubSub.subscribe('TOPIC', (msg, data) => {
- console.log(msg, data);
- });
- // 发布
- PubSub.publish('TOPIC', 'Hello PubSubJS!');
- // 取消订阅
- PubSub.unsubscribe(token);
复制代码 1.4 使用框架内置的状态管理工具
许多现代前端框架如 Vue.js、React 和 Angular 提供了内置的状态管理工具,可以用来实现发布订阅模式。例如:
Vue.js
- const EventBus = new Vue();
- // 组件A:发布事件
- EventBus.$emit('myEvent', 'Hello from Component A');
- // 组件B:订阅事件
- EventBus.$on('myEvent', (data) => {
- console.log(data);
- });
复制代码 React (使用 Context API 或 Redux)
- // 使用 Context API
- const MyContext = React.createContext();
- // 提供者组件
- const MyProvider = ({ children }) => {
- const [state, setState] = useState(null);
- const publish = (data) => {
- setState(data);
- };
- return (
- <MyContext.Provider value={{ state, publish }}>
- {children}
- </MyContext.Provider>
- );
- };
- // 订阅者组件
- const MySubscriber = () => {
- const { state, publish } = useContext(MyContext);
-
- useEffect(() => {
- console.log('State updated:', state);
- }, [state]);
复制代码 二、先后关系
可以先订阅后发布,那可以先发布后订阅吗?
在发布订阅模式中,先订阅后发布是非经常见的做法,因为这通常是实实际时变乱通知的根本方式:订阅者先准备好吸取消息,然后发布者发送消息。
然而,某些情况下,也大概需要在没有订阅者存在的情况下发布消息,并且在订阅者稍后订阅时能够收到之前发布的消息。要实现这种“先发布后订阅”的机制,可以采用以下几种方法:
2.1 缓存变乱数据
发布者在发布消息时,将消息暂时存储在一个缓存中,当新的订阅者订阅时,可以将缓存中的消息发送给订阅者。
- class EventBus {
- constructor() {
- this.listeners = {};
- this.cachedEvents = {};
- }
- on(event, listener) {
- if (!this.listeners[event]) {
- this.listeners[event] = [];
- }
- this.listeners[event].push(listener);
-
- // 如果有缓存的事件,立即触发
- if (this.cachedEvents[event]) {
- listener(this.cachedEvents[event]);
- }
- }
- emit(event, data) {
- if (this.listeners[event]) {
- this.listeners[event].forEach(listener => listener(data));
- }
- // 缓存事件数据
- this.cachedEvents[event] = data;
- }
- off(event, listener) {
- if (this.listeners[event]) {
- this.listeners[event] = this.listeners[event].filter(l => l !== listener);
- }
- }
- }
- const eventBus = new EventBus();
- // 发布事件
- eventBus.emit('message', 'This is a cached message');
- // 订阅事件
- eventBus.on('message', (data) => {
- console.log('Message received:', data); // Output: 'This is a cached message'
- });
复制代码 2.2 使用 Redux 或 Vuex 等状态管理工具
在前端框架中使用状态管理工具,例如 Redux(React)或 Vuex(Vue.js),可以在状态发生变化时订阅并触发相应的处理逻辑。状态管理工具的状态是持久的,订阅者在任何时间都可以获取当前的状态。
Redux 示例
- const { createStore } = require('redux');
- // 定义 action 类型
- const SET_MESSAGE = 'SET_MESSAGE';
- // 定义 action 创建函数
- const setMessage = (message) => ({
- type: SET_MESSAGE,
- payload: message
- });
- // 定义 reducer
- const messageReducer = (state = null, action) => {
- switch (action.type) {
- case SET_MESSAGE:
- return action.payload;
- default:
- return state;
- }
- };
- // 创建 Redux store
- const store = createStore(messageReducer);
- // 订阅 store
- const unsubscribe = store.subscribe(() => {
- const state = store.getState();
- console.log('State updated:', state);
- });
- // 发布 action
- store.dispatch(setMessage('This is a Redux message'));
复制代码 2.3 使用本地存储或 IndexedDB
如果需要跨页面持久化数据,可以使用欣赏器的本地存储(LocalStorage)或 IndexedDB。发布者将消息存储到本地存储中,订阅者在订阅时从本地存储中读取数据。
- // 发布消息
- localStorage.setItem('message', 'This is a persisted message');
- // 订阅消息
- const cachedMessage = localStorage.getItem('message');
- if (cachedMessage) {
- console.log('Message received:', cachedMessage);
- }
复制代码 通过这些方法,可以实现“先发布后订阅”的功能,确保订阅者能够收到之前发布的消息。选择哪种方法可以根据详细需求和技能栈来决定。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |