在 Javascript 中实现一种委托模式

Implementing kind of a delegation pattern in Javascript

我有两个 class,AB。我想要做的是在收到来自套接字的消息后将数据从 A 传递到 B

这是 classes 定义的简化外观:

class答:

export default class A {
  client;
  callbacks;
 
  constructor() {
    this.callbacks = {
      open: () => this.client.logger.debug('open'),
      close: () => this.client.logger.debug('closed'),
      message: (data) => {this.client.logger.log(data)}, //I want to pass this data object to class B
    };
    
    this.client = new Spot(constants.apiKey, constants.apiSecret, {
      baseURL: constants.baseURL,
      wsURL: constants.wsURL,
    });

    this.client.userData(listenKey, this.callbacks);

  }
}

我已经在 class B 的定义中有一个 属性 A:

export default class B {
  account;

  constructor() {
    this.account = new A();

    
  }
}

连接这两者的 correct/standard 方法是什么,所以每次 class A 的套接字消息回调是,我都会从 class A 得到一个 'data' 对象触发了吗?

我对 JS 有点陌生,但在 iOS 上,我们会使用委托模式和协议,上面写着:

  1. class A 将有一个代表 属性.
  2. 委托 (class B) 必须实现协议(在这种情况下,需要实现名为 didReceiveMessage(data) 的方法。
  3. 在那之后,当在 class A 中收到消息时,我们将(在上面显示的套接字消息回调中)像 this.delegate.didReceiveMessage(data).

这里的协议使用一般来说并不重要,但它是一个加号,因为从 A class,我们只能通过委托 属性 访问 didReceiveData(data) 方法,仅此而已( class B 的其他属性/方法不可见)。至少在 Swift/Obj-C 中是这样。我刚刚提到了它,因为我很好奇它在 JS 中也是如何完成的。

我想 Javascript 中有一些类似的机制,或者更多 standard/better 方法来实现这种对象之间的数据发送?

我不是 NodeJs 专家,但你可以使用类似 emitter plugin.

的东西

在 javascript 中,它看起来像这样:

function A() {
    Emitter(this);
    
    this.action = function() {
        console.log("something happened");
        
        this.emit("action", { prop: "value" });
    };
}

function B(a_instance) {
    // subscribe to "action" event
    a.on("action", function(data) {
        console.log(data.prop); // "value"
    });
};

var myA = new A();
var myB = new B(myA);

myA.action();

on iOS we would use a delegation pattern, with a protocol

你完全可以按照你描述的去做:

export default class A {
  client;
  delegate;
 
  constructor(delegate) {
    this.delegate = delegate;
    
    this.client = new Spot(constants.apiKey, constants.apiSecret, {
      baseURL: constants.baseURL,
      wsURL: constants.wsURL,
    });

    const callbacks = {
      open: () => this.client.logger.debug('open'),
      close: () => this.client.logger.debug('closed'),
      message: (data) => this.delegate.didReceiveMessage(data),
    };
    this.client.userData(listenKey, callbacks);
  }
}

export default class B {
  account;

  constructor() {
    this.account = new A(this);
  }
  
  didReceiveMessage(data) {
    console.log(data); // or whatever
  }
}

没有接口(协议)声明可以告诉 A 它可以在传递的 delegate 上访问哪些属性和方法,但合同当然存在。你应该用散文来记录它。 (或使用 TypeScript)。

另请注意您的 class A 如何与 Spot 客户端交互,它使用与事件处理程序方法传递对象非常相同的模式。

如果您的协议中只需要一个方法,JavaScript 中的一个更简单的模式就是只传递一个可调用函数:

export default class A {
  client;
 
  constructor(onMessage) {
    this.client = new Spot(constants.apiKey, constants.apiSecret, {
      baseURL: constants.baseURL,
      wsURL: constants.wsURL,
    });
    this.client.userData(listenKey, {
      open: () => this.client.logger.debug('open'),
      close: () => this.client.logger.debug('closed'),
      message: onMessage,
    });
  }
}

export default class B {
  account;

  constructor() {
    this.account = new A(this.didReceiveMessage.bind(this));
    // or inline:
    this.account = new A(data => {
      console.log(data); // or whatever
    });
  }
  
  didReceiveMessage(data) {
    console.log(data); // or whatever
  }
}