W Parku Jurajskim różne systemy muszą ze sobą współpracować - system monitoringu dinozaurów musi informować centrum bezpieczeństwa o zagrożeniach, a centrum bezpieczeństwa musi powiadomić ekipy ratunkowe. Standardowe wydarzenia przeglądarki (click, keydown, submit) obsługują interakcje użytkownika, ale co jeśli potrzebujemy własnych komunikatów między modułami aplikacji? Tutaj z pomocą przychodzą Custom Events - własne, niestandardowe wydarzenia.
Konstruktor
CustomEvent pozwala stworzyć wydarzenie o dowolnej nazwie i przekazać dodatkowe dane przez właściwość detail:1// Składnia: new CustomEvent(nazwaWydarzenia, opcje)
2const alertEvent = new CustomEvent('dinoAlert', {
3 detail: {
4 species: 'Velociraptor',
5 zone: 'B6',
6 threatLevel: 9
7 },
8 bubbles: true, // Czy wydarzenie bąbelkuje w górę drzewa DOM
9 cancelable: true // Czy można je anulować przez preventDefault()
10});Właściwość
detail może zawierać dowolne dane - obiekty, tablice, stringi, liczby. To główna różnica między CustomEvent a zwykłym Event, który nie ma pola detail.Aby "wystrzelić" wydarzenie, używamy metody
dispatchEvent() na dowolnym elemencie DOM:1// Wysłanie wydarzenia na konkretnym elemencie
2const monitorPanel = document.getElementById('monitor-panel');
3monitorPanel.dispatchEvent(alertEvent);
4
5// Wysłanie wydarzenia na całym dokumencie (globalny broadcast)
6document.dispatchEvent(alertEvent);Gdy wydarzenie zostanie wysłane, wszystkie zarejestrowane na nie listenery zostaną wywołane synchronicznie - w kolejności ich rejestracji.
Nasłuchiwanie na Custom Events działa identycznie jak na standardowe wydarzenia - za pomocą
addEventListener():1// Nasłuchiwanie na dowolnym elemencie
2document.addEventListener('dinoAlert', function(event) {
3 const { species, zone, threatLevel } = event.detail;
4
5 console.log(`ALERT: ${species} wykryty w strefie ${zone}!`);
6 console.log(`Poziom zagrożenia: ${threatLevel}/10`);
7
8 if (threatLevel >= 8) {
9 activateEmergencyProtocol(zone);
10 }
11});Połączmy wszystkie elementy w kompletny system komunikacji między modułami:
1// Moduł 1: Generator alertów
2function createParkAlert(alertType, message, data = {}) {
3 const alertEvent = new CustomEvent('parkAlert', {
4 detail: {
5 type: alertType,
6 message: message,
7 timestamp: new Date(),
8 data: data
9 },
10 bubbles: true
11 });
12
13 document.dispatchEvent(alertEvent);
14}
15
16// Moduł 2: Centralny system nasłuchujący
17document.addEventListener('parkAlert', (e) => {
18 const { type, message, timestamp, data } = e.detail;
19
20 console.log(`${timestamp.toLocaleTimeString()} - Alert ${type}: ${message}`);
21
22 switch(type) {
23 case 'security':
24 showSecurityAlert(message, data);
25 break;
26 case 'maintenance':
27 showMaintenanceNotification(message, data);
28 break;
29 case 'visitor':
30 showVisitorInfo(message, data);
31 break;
32 default:
33 showGeneralAlert(message);
34 }
35});
36
37// Moduł 3: Wykrywanie ucieczek dinozaurów
38function handleDinosaurEscape(dinosaurId) {
39 const dinosaur = getDinosaurById(dinosaurId);
40
41 createParkAlert('security', `ALARM! ${dinosaur.name} uciekł z wybiegu!`, {
42 dinosaurId: dinosaurId,
43 location: dinosaur.enclosure,
44 dangerLevel: dinosaur.dangerLevel
45 });
46
47 activateEmergencyProtocols();
48}Custom Events pozwalają zbudować prosty Event Bus - centralny punkt komunikacji między niezależnymi modułami aplikacji:
1class ParkEventBus {
2 constructor() {
3 this.target = new EventTarget();
4 }
5
6 emit(eventName, data) {
7 this.target.dispatchEvent(
8 new CustomEvent(eventName, { detail: data })
9 );
10 }
11
12 on(eventName, callback) {
13 const handler = (e) => callback(e.detail);
14 this.target.addEventListener(eventName, handler);
15 // Zwracamy funkcję do wyrejestrowania
16 return () => this.target.removeEventListener(eventName, handler);
17 }
18}
19
20const bus = new ParkEventBus();
21
22// Moduł monitoringu rejestruje się na alerty
23const unsubscribe = bus.on('fenceBreak', (data) => {
24 console.log(`Ogrodzenie w strefie ${data.zone} uszkodzone!`);
25});
26
27// Moduł sensorów wysyła alert
28bus.emit('fenceBreak', { zone: 'C3', voltage: 0 });
29
30// Gdy moduł jest niszczony - wyrejestrowanie
31unsubscribe();Dzięki Event Bus moduły nie muszą znać się nawzajem - komunikują się wyłącznie przez wydarzenia, co zapewnia luźne powiązanie (loose coupling) i łatwiejsze testowanie.