javascript - DOM外的浏览器Javascript中的自定义事件发射器/消费者
问题描述
目前我有以下结构,一个 ObjectWebsocketService
和多个FrontendController
s。
WebsocketService
侦听 websocket (duh) 并更新内部应用程序状态。这意味着在某些情况下必须使用新值更新前端。
为了使我的 UI 代码和应用程序逻辑很好地分离,我设想了一种设计,其中FrontendController
s 可以订阅事件,WebsocketService
并且很可能稍后会订阅其他服务。
我已阅读有关在 MDN 上创建和触发事件的文档。但所有这些都非常以 DOM 为中心。我的WebsocketService
显然没有addEventListener
功能。
我宁愿不使用第 3 方库。想到的一个技巧就是在id="events"
某个地方有一个 DOM 节点并让每个人都订阅它。然后dispatchEvent
s 在那个 Element 上,让FrontendController
s 决定他们关心的问题。
当然,我也可以为所有这些实现我自己的基础设施,但我也更愿意避免这种情况,因为我很懒。
这样做的干净方法是什么?或者有没有更好的解决方案来解耦我的应用程序逻辑和前端在普通的旧 javascript 中?
解决方案
我看到的简单可能性是:
让你的 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();
- 实现自己的 addEventListener 方法并使用现有机制
- 实现自己的 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();
无论您选择哪一个,您都必须声明自己的自定义事件。
推荐阅读
- python - Convert List to dictionary by key
- reactjs - Why is ConnectedProps not inferring the correct type?
- c - how to convert an integer into a return value of a process to use it in WEXITSTATUS in C
- python - Why is my tensorflow Roberta Model unable to train/finetune?
- python - Make a ROS node that does spatial median filtering on the "msg.ranges"
- wordpress - Varnish 301 redirecting loop Wordpress website
- php - Unable to share image and title with url on facebook through my web page?
- python - 如何优化比较两列之间的行值的余弦相似度函数?
- apache-spark - 如何检查结构化流中的 StreamingQuery 性能指标?
- flutter - 提供的身份验证凭据格式不正确或已过期。- 颤振 Facebook 登录