You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 23:45:05