From 1348f3402c9c15c37501c7cf48f6c63ae7f8c1d8 Mon Sep 17 00:00:00 2001 From: Melonai Date: Thu, 3 Jun 2021 02:10:52 +0200 Subject: Dynamic event handling architecture --- assets/src/network/channel/messages/handler.ts | 93 ++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 assets/src/network/channel/messages/handler.ts (limited to 'assets/src/network/channel/messages/handler.ts') diff --git a/assets/src/network/channel/messages/handler.ts b/assets/src/network/channel/messages/handler.ts new file mode 100644 index 0000000..5cfe327 --- /dev/null +++ b/assets/src/network/channel/messages/handler.ts @@ -0,0 +1,93 @@ +import { getChannel } from "../connection"; +import type { AnyMessage } from "./messages"; + +export type Handlers = { + [event: string]: EventHandler; +}; + +type EventHandler = { + tokenHandler: TokenHandler; + directHandlers: Handler[]; +}; + +export type TokenHandler = { + [token: string]: Handler; +}; + +export type Handler = (message?: Message) => void; + +export type UnregisterHandler = () => void; + +export function registerTokenHandler( + handlers: Handlers, + event: string, + token: string | null, + handler: Handler +): UnregisterHandler { + let eventHandler = handlers[event]; + + // If this event did not yet have any handlers registered we have to register it + if (eventHandler === undefined) { + eventHandler = { + tokenHandler: {}, + directHandlers: [], + }; + + handlers[event] = eventHandler; + + registerNewEvent(eventHandler, event); + } + + let unregister: UnregisterHandler; + + if (token === null) { + const directHandlers = eventHandler.directHandlers; + directHandlers.push(handler); + + unregister = () => { + const index = directHandlers.findIndex(h => h === handler); + directHandlers.splice(index, 1); + }; + } else { + const tokenHandler = eventHandler.tokenHandler; + tokenHandler[token] = handler; + + unregister = () => { + delete tokenHandler[token]; + }; + } + + return unregister; +} + +function registerNewEvent( + eventHandler: EventHandler, + event: string +) { + const callback = (data: Message) => { + handleEvent(eventHandler, data); + }; + + getChannel().on(event, callback); +} + +function handleEvent( + eventHandler: EventHandler, + message: Message +) { + if (message["token"] !== undefined) { + const token = message["token"]; + + const handler: Handler = eventHandler.tokenHandler[token]; + + if (handler === undefined) { + throw new Error("Received message for an unknown token."); + } + + handler(message); + } + + for (const handler of eventHandler.directHandlers) { + handler(message); + } +} -- cgit 1.4.1