Event Handling & Cross-Window Kommunikation
Übersicht
Das Event-System in p2d2 ermöglicht eine robuste, asynchrone Kommunikation zwischen verschiedenen Komponenten der Anwendung und unterstützt insbesondere die bidirektionale Kommunikation zwischen Hauptfenster und Editor-Fenstern. Das System basiert auf einem CustomEvent-basierten Ansatz mit erweiterten Funktionen wie Retry-Mechanismen, Throttling und Cross-Window-Propagation.
Architektur-Konzept
Kernkomponenten
- Event Dispatcher: Zentrale Klasse für Event-Dispatching mit Throttling-Unterstützung
- Event Console: Debugging-Oberfläche für Live-Event-Überwachung mit Filter- und Export-Funktionen
- Cross-Window Bridge: Bidirektionale Kommunikation zwischen Browser-Fenstern
- Event Queue: Retry-Mechanismus für zuverlässige Event-Verarbeitung
Datenfluss-Architektur
┌────────────────────┐ ┌──────────────────────┐ ┌──────────────────┐
│ Hauptfenster │ │ Cross-Window Bridge │ │ Editor-Fenster │
│ │ │ │ │ │
│ • Event Console │ ◄────┤ • initialize() │────► │ • Event Console │
│ • Event Dispatch │ │ • registerWindow() │ │ • Event Dispatch │
│ • Event Listener │ │ • broadcastEvent() │ │ • Event Listener │
└────────────────────┘ └──────────────────────┘ └──────────────────┘
│ │ │
└────────────────────────────┼───────────────────────────────┘
│
┌───────────▼────────────┐
│ window.postMessage() │
│ (Same-Origin Policy) │
└────────────────────────┘Debugging in der Produktionsumgebung
Die EventConsole ist auch auf www.data-dna.eu verfügbar:
Aktivierung:
- Via URL: Füge
?debug=eventshinzu:https://www.data-dna.eu?debug=events - Via Keyboard: Drücke
Ctrl+Shift+E(Windows/Linux) oderCmd+Shift+E(Mac)
Nutzung:
- Toggle:
Ctrl+Shift+E - Filter: Textfeld oben rechts
- Export: "Copy JSON" Button für Bug-Reports
Event-Typologie
Kategorien und Prioritäten
Das Event-System kategorisiert Events nach Funktionsbereichen und priorisiert sie für die Cross-Window-Kommunikation:
| Kategorie | Beschreibung | Beispiele | Cross-Window-Priorität |
|---|---|---|---|
| Kommune | Kommunen-bezogene Events | kommunen:focus, kommunen:selected | Mittel-Hoch |
| Map | Karteninteraktionen | map:ready, map:moveend, map:zoomend | Mittel |
| WFS | WFS-Datenoperationen | wfs:load:start, wfs:feature:created | Hoch |
| Editor | Editor-Operationen | editor:ready, editor:feature:modified | Hoch |
| UI | Benutzeroberfläche | ui:panel:toggle, crs:change | Niedrig |
Event-Inventar
| Event-Typ | Kategorie | Beschreibung | Priorität | Cross-Window | Implementiert |
|---|---|---|---|---|---|
p2d2:kommunen:focus | Kommune | Fokus auf eine Kommune (Zoom/Pan) | Mittel | Nein | Ja |
p2d2:kommunen:selected | Kommune | Kommune ausgewählt | Hoch | Ja | Ja |
p2d2:map:ready | Map | Karte initialisiert | Hoch | Ja | Ja |
p2d2:map:moveend | Map | Kartenbewegung abgeschlossen | Niedrig | Nein | Ja |
p2d2:map:zoomend | Map | Zoom-Änderung abgeschlossen | Niedrig | Nein | Ja |
p2d2:wfs:load:start | WFS | WFS-Ladevorgang gestartet | Hoch | Ja | Ja |
p2d2:wfs:load:complete | WFS | WFS-Ladevorgang erfolgreich | Hoch | Ja | Ja |
p2d2:wfs:load:error | WFS | WFS-Ladevorgang fehlgeschlagen | Hoch | Ja | Ja |
p2d2:wfs:feature:created | WFS | Feature erstellt | Hoch | Ja | Ja |
p2d2:wfs:feature:updated | WFS | Feature aktualisiert | Hoch | Ja | Ja |
p2d2:wfs:feature:deleted | WFS | Feature gelöscht | Hoch | Ja | Ja |
p2d2:editor:ready | Editor | Editor-Fenster initialisiert | Hoch | Ja | Ja |
p2d2:editor:feature:modified | Editor | Feature im Editor modifiziert | Hoch | Ja | Ja |
p2d2:editor:mode:change | Editor | Modus (navigate/edit) geändert | Hoch | Ja | Ja |
p2d2:editor:feature:selected | Editor | Feature im Editor ausgewählt | Hoch | Ja | Ja |
Cross-Window Kommunikation
Architektur
Die Cross-Window-Kommunikation ermöglicht die Synchronisation zwischen Hauptfenster und Editor-Fenstern über die window.postMessage() API unter strikter Einhaltung der Same-Origin Policy.
Kernkomponenten
Cross-Window Bridge (
cross-window-events.ts):- Initialisierung und Fenster-Registrierung
- Bidirektionale Event-Propagation
- Fenster-Identifikation und Lifecycle-Management
Event Console Erweiterung:
- Source-Labeling (
🏠 Main,🪟 Editor) - Cross-Window-Markierung (
⚡ Cross-Window) - Filterung nach Event-Quelle
- Source-Labeling (
Event Metadata:
typescriptinterface LogEntryMeta { source?: 'main' | 'editor' | string; windowId?: string; crossWindow?: boolean; retryCount?: number; throttled?: boolean; success?: boolean; error?: string; }
Implementierungsdetails
Event-Dispatch mit Cross-Window-Propagation
// Beispiel: Cross-Window Event Dispatch
function dispatchCrossWindowEvent(
eventName: string,
detail: any,
options: { crossWindow: boolean } = { crossWindow: false }
): void {
// 1. Lokales Event feuern
const event = new CustomEvent(eventName, { detail });
window.dispatchEvent(event);
// 2. In Event Console loggen
eventConsole.logEvent(eventName, detail, {
source: getWindowType(),
crossWindow: options.crossWindow,
windowId: getWindowId()
});
// 3. Bei Cross-Window-Flag an andere Fenster propagieren
if (options.crossWindow && crossWindowBridge) {
crossWindowBridge.broadcastToOtherWindows(eventName, detail);
}
}Fenster-Registrierung und Lifecycle
// Hauptfenster: Editor-Fenster registrieren
function registerEditorWindow(editorWindow: Window): void {
editorWindows.add(editorWindow);
// Cleanup bei Fensterschließung
const intervalId = setInterval(() => {
if (editorWindow.closed) {
editorWindows.delete(editorWindow);
clearInterval(intervalId);
}
}, 1000);
}
// Editor-Fenster: Bei Hauptfenster registrieren
function initializeEditorBridge(): void {
if (window.opener) {
window.opener.postMessage({
type: 'EDITOR_REGISTER',
windowId: getWindowId(),
source: 'editor'
}, window.location.origin);
}
}Sicherheitsaspekte
- Same-Origin Policy: Nur Kommunikation zwischen Fenstern gleicher Herkunft
- Event-Validation: Eingangs-Events werden auf Gültigkeit geprüft
- Window-Verifikation: Nur registrierte Fenster dürfen Events empfangen
- Payload-Limits: Maximale Event-Größen zur Vermeidung von DoS-Angriffen
Event Console
Funktionsumfang
Die Event Console dient als Debugging- und Monitoring-Tool mit folgenden Features:
- Live-Event-Überwachung: Echtzeit-Anzeige aller System-Events
- Source-Labeling: Visuelle Unterscheidung nach Event-Quelle
🏠 Main: Events aus dem Hauptfenster (grün)🪟 Editor: Events aus Editor-Fenstern (lila)⚡ Cross-Window: Cross-Window-Events (gelb)
- Filterung: Nach Event-Typ, Detail-Inhalt oder Quelle
- Export: JSON-Export aller Events in die Zwischenablage
- Persistenz: Console-Zustand im LocalStorage (24h Gültigkeit)
Bedienung
- Öffnen/Schließen:
Ctrl+Shift+E(Windows/Linux) oderCmd+Shift+E(Mac) - Filter: Text-Eingabe im Filter-Input
- Clear: Alle Events löschen
- Export: "Copy JSON"-Button für vollständigen Export
Priorisierungsstrategie
Phase 1: Kritische Cross-Window-Events
| Event | Priorität | Begründung |
|---|---|---|
p2d2:editor:ready | Hoch | Grundstatus des Editor-Fensters |
p2d2:map:ready | Hoch | Grundstatus des Hauptfensters |
p2d2:editor:feature:modified | Hoch | Live-Änderungen vom Editor |
p2d2:wfs:load:* | Hoch | Ladezustände vom Hauptfenster |
Phase 2: Erweiterte Synchronisation
| Event | Priorität | Begründung |
|---|---|---|
p2d2:wfs:feature:* | Hoch | Vollständige Feature-Synchronisation |
p2d2:editor:mode:change | Mittel | Editor-Kontext teilen |
p2d2:layer:toggle | Mittel | Konsistente Layer-Darstellung |
Phase 3: Debugging & Monitoring
| Event | Priorität | Begründung |
|---|---|---|
p2d2:map:moveend | Niedrig | Karteninteraktionen verfolgen |
p2d2:ui:panel:toggle | Niedrig | UI-Status überwachen |
Technische Implementierung
Event-System Konfiguration
const EVENT_CONFIG = {
// Retry-Mechanismus
MAX_RETRIES: 3,
RETRY_DELAY_MS: 250,
// Throttling
THROTTLE_MS: 200,
// Cross-Window
WINDOW_ID_PREFIX: 'p2d2-window-',
MESSAGE_TARGET_ORIGIN: window.location.origin,
// Event Console
MAX_LOG_ENTRIES: 50,
STORAGE_KEY: 'p2d2:debug:events',
STORAGE_TTL_MS: 24 * 60 * 60 * 1000 // 24 Stunden
};Performance-Optimierungen
- Event Throttling: Verhindert zu häufige Events (z.B.
map:moveend) - Lazy Propagation: Cross-Window-Kommunikation nur bei Bedarf
- Queue-Batching: Mehrere Events könnten gebatcht werden
- Selective Listening: Komponenten können spezifische Events abonnieren
Error-Handling
- Retry-Mechanismus: 3-stufiger Retry für fehlgeschlagene Events
- Graceful Degradation: Fallback bei Cross-Window-Kommunikationsfehlern
- Error-Logging: Umfassendes Logging mit Kontext-Informationen
- User Feedback: Visuelle Rückmeldung bei kritischen Fehlern
Qualitätssicherung
Automatisierte Tests
- Unit Tests: Event-Dispatch und Cross-Window-Kommunikation
- Integrationstests: Fenster-übergreifende Event-Propagation
- E2E Tests: Komplette Workflows mit Cypress/Puppeteer
Manuelle Testszenarien
Basisfunktionalität:
- Events erscheinen in der Event Console
- Filter-Funktion arbeitet korrekt
- Export erzeugt gültiges JSON
Cross-Window-Kommunikation:
- Events werden zwischen Fenstern propagiert
- Source-Labels werden korrekt angezeigt
- Fenster-Registrierung und Cleanup
Fehlerbehandlung:
- Netzwerkausfälle während der Kommunikation
- Fensterschließung während aktiver Session
- Ungültige Event-Payloads
Monitoring-Metriken
- Event-Throughput: Anzahl Events pro Sekunde
- Cross-Window-Latenz: Zeit für Event-Propagation zwischen Fenstern
- Error-Rate: Anteil fehlgeschlagener Events
- Console-Nutzung: Häufigkeit der Event Console-Nutzung
Best Practices
Event-Design
- Konsistente Namenskonvention:
domain:component:action(z.B.p2d2:editor:feature:modified) - Strukturierte Payloads: Klare Interfaces für Event-Details
- Minimale Payload-Größe: Nur notwendige Daten übertragen
- Immutable Daten: Events sollten unveränderlich sein
Cross-Window-Kommunikation
- Selective Propagation: Nur notwendige Events cross-window senden
- Window-Lifecycle: Saubere Registrierung/Deregistrierung
- Error-Resilience: Robust gegenüber Fenster-Ausfällen
- Security-First: Strikte Origin-Überprüfung
Debugging mit Event Console
- Source-Filterung: Nach
mainodereditorfiltern für Problem-Isolation - JSON-Export: Für detaillierte Analyse und Bug-Reports
- Performance-Monitoring: Event-Häufigkeit und Latenz beobachten
- Reproduktion: Event-Sequenzen für Bug-Reproduktion exportieren