Пользовательский источник событий / потребители в браузере Javascript вне DOM - PullRequest
0 голосов
/ 30 июня 2018

В настоящее время у меня есть следующая структура, объект WebsocketService и несколько FrontendController с.

WebsocketService прослушивает веб-сокет (duh) и обновляет внутреннее состояние приложения. Это означает, что в некоторых случаях внешний интерфейс должен обновляться новыми значениями.

Для того, чтобы мой код пользовательского интерфейса и логика приложения были хорошо разделены, я представляю проект, в котором FrontendController могут подписаться на события, отправленные WebsocketService и, скорее всего, другими Сервисами позже.

Я прочитал документацию для Создание и запуск событий в MDN . Но все это очень ориентировано на DOM. У моего WebsocketService, очевидно, нет функции addEventListener.

Я бы предпочел не использовать сторонние библиотеки. Хак, который приходит на ум, просто имеет где-то id="events" DOM Node, и каждый подписывается на это. Затем dispatchEvent s на этом Элементе и пусть FrontendController s решают, что им небезразлично.

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

Какой чистый способ сделать это? Или есть намного лучшее решение, чтобы отделить логику и интерфейс моего приложения от простого старого javascript?

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Легкие возможности, как я их вижу:

  1. Заставьте ваш WebsocketService расширить HTMLElement

    Преимущества:

    • Easy
    • Вы наследуете методы, связанные с событиями, включая addEventListener и dispatchEvent.

    Недостатки:

    • Вы наследуете все методы и свойства DOM, которые никогда не будете использовать.
    • Частично поддерживается (FireFox должен работать с простой, но особой конфигурацией, Edge / Explorer не поддерживает его)

    Пример:

//add some event
let piggyEvent = document.createEvent('Event');
piggyEvent.initEvent('piggy', true, true);

class WebSocketService extends HTMLElement {
  constructor() {
    super();
  }
  onDataArrival() {
    //some code here...
  }
  onConnectionLoss() {
    //some code here...
  }
  onHappyPiggyArrival() {
    this.dispatchEvent(piggyEvent);
  }
}

class FrontEndService {
  constructor(socketService) {
    this.socketService = socketService;
  }
  subscribe() {
    this.socketService.addEventListener('piggy', (event) => {
      alert("A new piggy has arrived, do something with it!");
    })
  }
}

//You must declare the new element
customElements.define('websocket-service', WebSocketService);

//Now let's try it
let socService = new WebSocketService(),
  frontService = new FrontEndService(socService);
frontService.subscribe();

//nothing happens until...
socService.onHappyPiggyArrival();
  1. Реализуйте свой собственный метод addEventListener и используйте существующий механизм
  2. Реализация собственного механизма событий lite

//add some event
let piggyEvent = document.createEvent('Event');
piggyEvent.initEvent('piggy', true, true);


class EventSupportedElement {
  constructor() {
    this.eventRegsitry = new Map();
  }

  _initRegEntry(entryName) {
    if (!this.eventRegsitry.has(entryName)) {
      this.eventRegsitry.set(entryName, []);
    }
    return this.eventRegsitry.get(entryName);
  }

  addEventListener(eventName, callback) {
    this._initRegEntry(eventName).push(callback);
  }

  removeEventListener(eventName, callback) {
    let eventNameCallbacks = this.eventRegsitry.get(eventName);
    if (eventNameCallbacks && eventNameCallbacks.indexOf(callback) !== -1) {
      eventNameCallbacks.splice(eventNameCallbacks.indexOf(callback), 1);
    }
  }

  dispatchEvent(eventObject) {
    if (eventObject.type && this.eventRegsitry.get(eventObject.type)) {
      this.eventRegsitry.get(eventObject.type).forEach((callback) => {
        //add any data to the event / use custom event and trigger
        callback(eventObject);
      });
    }
  }
}

class WebSocketService extends EventSupportedElement {
  onDataArrival() {
    //some code here...
  }

  onConnectionLoss() {
    //some code here...
  }

  onHappyPiggyArrival() {
    this.dispatchEvent(piggyEvent);
  }
}

class FrontEndService {
  constructor(socketService) {
    this.socketService = socketService;
  }

  subscribe(eventName, callback) {
    this.socketService.addEventListener(eventName, callback);
  }
  unsubscribe(eventName, callback) {
    this.socketService.removeEventListener(eventName, callback);
  };
}

//Now let's try it
let socService = new WebSocketService(),
  frontService = new FrontEndService(socService),
  onPiggyFn = (event) => {
    alert("A new piggy has arrived, do something with it!");
  };
frontService.subscribe('piggy', onPiggyFn);

//nothing happens until...
socService.onHappyPiggyArrival();

//now unsubscribe
frontService.unsubscribe('piggy', onPiggyFn);

//nothing happens...
socService.onHappyPiggyArrival();

Независимо от того, какой из них вы выберете, вам придется объявлять свои собственные события.

0 голосов
/ 04 июля 2018

Вы можете просто создать свою собственную систему пабов / подсистем, например: https://davidwalsh.name/pubsub-javascript

Или используйте программу с открытым исходным кодом: https://github.com/mroderick/PubSubJS

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...