This is the second day of my participation in the August More text Challenge. For details, see: August More Text Challenge

Opening Nonsense: This article is about the publish/subscribe model. Many of you have heard of the Observer model. There are sources on the Internet that say there are two different design patterns, and there is one model. Don’t worry too much

Opening wedge: The Tokyo Olympic Games has opened for a period of time, in this Olympic Games in China’s Olympic athletes have achieved very good results, up to now (2021.08.05), China has won 34 gold 24 silver 16 bronze, at work time also always pay attention to the details of the competition, but for workers to see the complete game may not be able to do, But the occasional refresher of the Olympic medal tally is no small task. Then I thought it would be good if someone could inform me of the change of the medal count in time. Suppose CSDN provided the medal data. After I clicked “Follow” and subscribe, CSDN would then push the latest medal tally to me in real time

There are three main steps to implementing a publish-subscribe model in code to get Olympic MEDALS

  • Save all subscription information, eventList
  • Provide a subscription method to save subscribed events to the eventList
  • Provides a publishing method to publish all subscribed events
class Emitter {
  constructor() {
    // Save all subscribed events
    this.eventList = {};
  }
  // Subscribe to event: event name, event handler
  subscribe(eventName, fn) {
    if (!this.eventList[eventName]) {
      this.eventList[eventName] = [];
    }
    this.eventList[eventName].push(fn);
  }
  // Publish event: event name, parameters
  publish(eventName, ... args) {
    const fns = this.eventList[eventName];
    if(! fns || fns.length ===0) {
      return;
    }
    fns.forEach((fn) = > {
      fn.apply(this, args); }); }}Copy the code

That’s a simple implementation of the publish-subscribe pattern, and write some test code

const csdn = new Emitter();
csdn.subscribe("china-medal".function (medals) {
  console.log("China's medal count:", medals);
});

csdn.publish("china-medal"."34 gold, 24 silver and 16 bronze.");
csdn.publish("china-medal"."43 gold, 30 silver, 27 bronze");
Copy the code

Output results:

China's total number of MEDALS: 34 gold, 24 silver, 16 bronzeCopy the code

If the Olympics are over, I don’t need to pay attention to the medal count any more, then I need an unsubscribe event remove

class Emitter {
 // Omit the other code XXX
  remove(eventName, fn) {
    const fns = this.eventList[eventName];
    if(! fns || fns.length ===0) {
      return;
    }
    const idx = fns.findIndex((item) = > item === fn);
    fns.splice(idx, 1); }}Copy the code

Let’s go ahead and test the code to see if you can unsubscribe correctly

const csdn = new Emitter();
const fn = function (medals) {
  console.log("China's medal count:", medals);
};
csdn.subscribe("china-medal", fn);

csdn.publish("china-medal"."34 gold, 24 silver and 16 bronze.");
csdn.publish("china-medal"."43 gold, 30 silver, 27 bronze");

setTimeout(() = > {
  csdn.remove("china-medal", fn);
  csdn.publish("china-medal"."The Olympics are over. We can't release it.");
}, 1000);
Copy the code

Not bad, the publish-subscribe feature is quite complete.

If you want to see more about publish-subscribe applications, check out my previous post:

  • The data update view process for Vue 2.x also makes use of the published_subscribe model. For those interested, see another of my minimalist series, VUE Responsive Implementation (2.x).

  • The Vue form component also uses a publish-subscribe model. Note of interest here: The minimalist series, Vue3. X Form component