张裕 发表于 2024-6-14 21:19:10

WHAT - 发布订阅

在前端开辟中,发布订阅是一种常见的开辟场景,允许一个对象(发布者)发布变乱,而多个对象(订阅者)可以订阅并吸取这些变乱。
发布订阅在设计模式中,可以理解为 观察者模式 / 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) {
      this.listeners = [];
    }
    this.listeners.push(listener);
}

emit(event, data) {
    if (this.listeners) {
      this.listeners.forEach(listener => listener(data));
    }
}

off(event, listener) {
    if (this.listeners) {
      this.listeners = this.listeners.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 = 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);
}, );
二、先后关系

可以先订阅后发布,那可以先发布后订阅吗?
在发布订阅模式中,先订阅后发布是非经常见的做法,因为这通常是实实际时变乱通知的根本方式:订阅者先准备好吸取消息,然后发布者发送消息。
然而,某些情况下,也大概需要在没有订阅者存在的情况下发布消息,并且在订阅者稍后订阅时能够收到之前发布的消息。要实现这种“先发布后订阅”的机制,可以采用以下几种方法:
2.1 缓存变乱数据

发布者在发布消息时,将消息暂时存储在一个缓存中,当新的订阅者订阅时,可以将缓存中的消息发送给订阅者。
class EventBus {
constructor() {
    this.listeners = {};
    this.cachedEvents = {};
}

on(event, listener) {
    if (!this.listeners) {
      this.listeners = [];
    }
    this.listeners.push(listener);
   
    // 如果有缓存的事件,立即触发
    if (this.cachedEvents) {
      listener(this.cachedEvents);
    }
}

emit(event, data) {
    if (this.listeners) {
      this.listeners.forEach(listener => listener(data));
    }
    // 缓存事件数据
    this.cachedEvents = data;
}

off(event, listener) {
    if (this.listeners) {
      this.listeners = this.listeners.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企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: WHAT - 发布订阅