在 JavaScript 中创建订阅和取消订阅而不传递订阅者 ID

Creating a subscribe and unsubscribe without passing the subscribers Id in JavaScript

概览

我正在创建一个简单的订阅和取消订阅服务。我正在创建它,因为模式很简单,我们可以避免添加附加依赖项。

模式

模式很简单,你有一个回调数组。

subscribers = [];

订阅、取消订阅和发布三个函数。

subscribe(callback){
  //code
}
unsubscribe(){
  //code
}
publish(data){
  //code
}

问题

理想情况下,这就是您需要的所有信息,但是我还没有找到一种方法来干净地订阅和取消订阅,而无需传递某种 ID 来了解要从订阅者数组中删除哪个函数。从订阅函数的调用者那里提取函数 ID 会很好。我发现有一种方法可以通过 caller and callee 执行此操作,但不应使用它们。那么有没有一个选项可以从订阅者的调用者那里捕获一个唯一标识符?

如果您愿意更改模式,可以让 subscribe 创建一个取消订阅函数,该函数将回调作为其闭包的一部分,然后 return 该函数。

subscribe(callback) {
   subscribers.push(callback);
   return function() {
      const index = subscribers.indexOf(callback);
      if (index > -1) {
         subscribers.splice(index, 1);
      }
   };
}
//unsubscribe() {} // Doesn't exist any more on the service
publish(data) {
   //code
}

所以当你的另一部分代码订阅时,它会保存一个对取消订阅函数的引用,以备后用。例如:

const unsubscribe = MyEventService.subscribe(function (data) {
   console.log('subscription fired!', data)
 });

// later, when this code needs to tear down
unsubscribe();

如果您希望保留调用服务以取消订阅的模式,我认为除了传递一些东西(标识符或再次传递回调函数)之外别无选择。

你可以做 redux 做的事情:

不是使用专用的 unsubscribe() 函数,而是 return 从 subscribe() 函数中删除订阅者的回调,即:

let subscribers  = [];
const subscribe = subscriber => {
  subscribers.push(subscriber);
  return () => { 
    subscribers = subscribers.filter( s => s !== subscriber);
  }
}

//To subscribe
const unsubscribe = subscribe(() => doSomethingWhenEventFires());
//To unsubscribe
unsubscribe();