JavaScript实现委托模式 将类A的Socket消息数据传递给类B的方法
JS实现类A到类B的Socket消息传递的常用方案
JS本身没有原生的Protocol语法,但可以通过运行时校验实现和iOS委托模式几乎一致的效果,也有其他更符合JS开发习惯的实现方案,以下是三种最常用的标准实现:
方案1:类委托模式(和iOS使用习惯完全对齐)
完全复刻你熟悉的委托逻辑,额外加运行时校验模拟Protocol的约束,A类仅能访问约定的didReceiveMessage方法,不会暴露B类的其他属性和方法:
修改后的A类代码
export default class A { client; callbacks; delegate; // 委托属性 constructor() { this.callbacks = { open: () => this.client.logger.debug('open'), close: () => this.client.logger.debug('closed'), message: (data) => { this.client.logger.log(data); // 校验委托存在且实现了约定方法后调用 if (this.delegate && typeof this.delegate.didReceiveMessage === 'function') { this.delegate.didReceiveMessage(data); } }, }; this.client = new Spot(constants.apiKey, constants.apiSecret, { baseURL: constants.baseURL, wsURL: constants.wsURL, }); this.client.userData(listenKey, this.callbacks); } // 可选:封装委托设置方法,加校验模拟Protocol强制要求,不符合规则直接抛错 setDelegate(delegate) { if (typeof delegate.didReceiveMessage !== 'function') { throw new Error('委托对象必须实现didReceiveMessage方法'); } this.delegate = delegate; } }
修改后的B类代码
export default class B { account; constructor() { this.account = new A(); // 将自身设置为A的委托 this.account.setDelegate(this); } // 实现约定的委托方法 didReceiveMessage(data) { // 此处即可拿到A传递的socket消息数据,编写业务逻辑即可 console.log('收到A传递的消息:', data); } }
方案2:回调注入(轻量场景首选)
如果仅需要传递消息这一个能力,不需要整套委托逻辑,直接给A暴露设置消息回调的方法即可,是JS最常用的轻量实现:
修改后的A类代码
export default class A { client; callbacks; #messageCallback; // JS私有属性,外部无法直接访问,安全性更高 constructor() { this.callbacks = { open: () => this.client.logger.debug('open'), close: () => this.client.logger.debug('closed'), message: (data) => { this.client.logger.log(data); // 存在回调则执行 this.#messageCallback?.(data); }, }; // 其余初始化逻辑不变 } // 暴露设置消息回调的方法 setMessageHandler(callback) { if (typeof callback !== 'function') { throw new Error('参数必须为函数类型'); } this.#messageCallback = callback; } }
修改后的B类代码
export default class B { account; constructor() { this.account = new A(); // 传入消息处理方法,箭头函数避免this指向问题 this.account.setMessageHandler(data => this.handleMessage(data)); } handleMessage(data) { // 处理收到的消息 } }
方案3:发布订阅模式(多监听者场景首选)
如果后续可能有多个类都需要监听A的Socket消息,用发布订阅模式扩展性更好,支持多订阅者同时接收消息:
修改后的A类代码
export default class A { client; callbacks; #subscribers = []; // 存储所有订阅者的回调函数 constructor() { this.callbacks = { open: () => this.client.logger.debug('open'), close: () => this.client.logger.debug('closed'), message: (data) => { this.client.logger.log(data); // 通知所有订阅者 this.#subscribers.forEach(callback => callback(data)); }, }; // 其余初始化逻辑不变 } // 订阅消息,返回取消订阅的方法 subscribe(callback) { if (typeof callback !== 'function') return; this.#subscribers.push(callback); return () => { this.#subscribers = this.#subscribers.filter(sub => sub !== callback); }; } }
修改后的B类代码
export default class B { account; #unsubscribe; constructor() { this.account = new A(); // 订阅消息,保存取消订阅的方法用于实例销毁时释放资源 this.#unsubscribe = this.account.subscribe(data => this.handleMessage(data)); } handleMessage(data) { // 处理收到的消息 } // 实例销毁时调用,避免内存泄漏 destroy() { this.#unsubscribe?.(); } }
选型建议
- 习惯iOS委托模式、A和B是一对一固定委托关系:选方案1
- 仅需要简单一对一消息传递,没有其他委托逻辑:选方案2
- 后续可能有多个对象需要监听A的消息:选方案3
内容的提问来源于stack exchange,提问作者Whirlwind
相关产品推荐
相关产品推荐

