Building a simple PubSub system in JavaScript

В недавнем проекте, построенном в сервисе [web push](/ design-a-webpush-service /), я хотел, чтобы мой пользовательский интерфейс отвечал на события уровня приложения (семантически, если хотите), потому что было несколько компонентов, которым требуется информация от системы, но не зависят друг от друга, и я хотел, чтобы они могли управлять собой независимо от «бизнес-логики».

Я осматривал множество различных инструментов, чтобы помочь мне, но поскольку у меня часто бывает тяжелый случай синдрома NIH и тот факт, что я думаю, что люди могут быстро реализовать свои собственные инфраструктурные элементы, я решил быстро сбить простой клиент- сторона службы PubSub & mdash; он работал очень хорошо для моих нужд.

Я обсуждал, следует ли использовать пользовательское DOM Event и использовать существующую инфраструктуру, которую DOM уже предоставляет разработчикам & mdash; возможность событий и событий потребления с использованием addEventListener & mdash; но единственная проблема заключалась в том, что вы должны повесить обработчик событий из элемента DOM или окна, потому что вы не можете иметь модель, которая наследует или смешивает в «EventTarget».

_ ** Мысль: ** наличие «EventTarget» в качестве объекта поможет устранить необходимость создания пользовательских систем PubSub.

Имея в виду это ограничение, желание кодировать что-то и склонность к нежеланию ошибок, которые я создаю, я набросал приблизительный план:

/* When a user is added, do something useful (like update UI) */
EventManager.subscribe('useradded', function(user) {
  console.log(user)
});

/* The UI submits the data, lets publish the event. */
form.onsubmit(function(e) {
  e.preventDefault();

  // do something with user fields

  EventManager.publish('useradded', user);
})

Все это не ново. Redux и многие другие системы уже делают это, и во многих случаях они также помогают вам управлять состоянием. В моей голове у меня действительно нет состояния, которое нуждается в модели, которая пересекается в состояние уже в браузере.

Реализация довольно проста в реализации, и абстракция для меня очень полезна.

var EventManager = new (function() {
  var events = {};

  this.publish = function(name, data) {
    var handlers = events[name];
    if(!!handlers === false) return;
    handlers.forEach(function(handler) {
      handler.call(this, data);
    });
  };

  this.subscribe = function(name, handler) {
    var handlers = events[name];
    if(!!handlers === false) {
      handlers = events[name] = [];
    }
    handlers.push(handler);
  };

  this.unsubscribe = function(name, handler) {
    var handlers = events[name];
    if(!!handlers === false) return;

    var handlerIdx = handlers.indexOf(handler);
    handlers.splice(handlerIdx);
  };
});

Изменить: Удалено использование обещаний.

И вот мы. Простая система pubsub, которая, вероятно, полна ошибок, но мне она нравится. :) Я поместил его в github, если вас это интересует.

About Me: Paul Kinlan

I lead the Chrome Developer Relations team at Google.

We want people to have the best experience possible on the web without having to install a native app or produce content in a walled garden.

Our team tries to make it easier for developers to build on the web by supporting every Chrome release, creating great content to support developers on web.dev, contributing to MDN, helping to improve browser compatibility, and some of the best developer tools like Lighthouse, Workbox, Squoosh to name just a few.