gpt4 book ai didi

javascript - DOM 之外的浏览器 Javascript 中的自定义事件发射器/消费者

转载 作者:行者123 更新时间:2023-11-29 23:19:55 25 4
gpt4 key购买 nike

目前我有以下结构,一个对象 WebsocketService 和多个 FrontendController

WebsocketService 监听 websocket (duh) 并更新内部应用程序状态。这意味着在某些情况下,前端必须使用新值进行更新。

为了让我的 UI 代码和应用程​​序逻辑很好地分离,我设想了一种设计,其中 FrontendController 可以订阅 WebsocketService 发出的事件,很可能稍后还有其他服务.

我已阅读 Creating and triggering events on MDN 的文档.但所有这些都是以 DOM 为中心的。我的 WebsocketService 显然没有 addEventListener 函数。

我宁愿不使用第 3 方库。我想到的一个 hack 就是在某个地方有一个 id="events" DOM 节点并让每个人都订阅它。然后 dispatchEvent 在该元素上,并让 FrontendController 决定他们关心。

当然我也可以为所有这些实现我自己的基础设施,但我也宁愿避免那样做,因为我很懒。

执行此操作的干净方法是什么?或者是否有更好的解决方案来分离我的应用程序逻辑和普通旧 javascript 中的前端?

最佳答案

我认为最简单的可能性是:

  1. 让您的 WebsocketService 扩展 HTMLElement

    优点:

    • 简单
    • 您继承与事件相关的方法,包括 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. 实现您自己的精简事件机制

//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();

无论选择哪一个,您都必须声明自己的自定义事件。

关于javascript - DOM 之外的浏览器 Javascript 中的自定义事件发射器/消费者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51110935/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com