-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
122 lines (99 loc) · 3.41 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import {
useCallback,
useState,
useEffect,
} from 'react';
interface EventCallback {
(params: any): void;
}
interface Listener {
callback: EventCallback;
listenerId: string;
}
interface EventStore {
[eventName: string]: Listener[];
}
const registeredEvents: EventStore = {};
const listenHandle = (store: EventStore = registeredEvents) => (
eventName: string,
callback: EventCallback
): { listenerId: string; store: EventStore } => {
if (!eventName) throw new Error('eventName is required');
if (!callback || typeof callback !== 'function') throw new Error('eventCallback is required');
if (!store[eventName]) store[eventName] = [];
const listenerId = `${Math.random().toString(32)}-${Math.random().toString(32)}-${Math.random().toString(32)}`;
store[eventName].push({
callback,
listenerId,
});
return {
listenerId,
store,
};
};
const unlistenHandle = (store: EventStore = registeredEvents) => (
eventName: string,
listenerId: string
): EventStore => {
if (!eventName) throw new Error('eventName is required');
if (!listenerId) throw new Error('listenerId is required');
if (!store[eventName]) store;
store[eventName] = store[eventName].filter((cb) => cb.listenerId !== listenerId);
return store;
};
const removeAllListenersByEventHandle = (eventName: string): boolean => {
if (!eventName) throw new Error('eventName is required');
if (!registeredEvents[eventName]) return false;
registeredEvents[eventName] = [];
return true;
};
const emitHandle = (store: EventStore = registeredEvents) => (
eventName: string,
params: any
): void => {
if (!eventName) throw new Error('eventName is required');
if (store[eventName]) {
store[eventName].forEach(async (cb) => {
cb.callback(params);
});
}
};
export function getAllEventsName(): string[] {
return Object.keys(registeredEvents);
}
export function useEvents() {
const [privateRegisteredEvents, setPrivateRegisteredEvents] = useState<EventStore>({});
const listen = useCallback((eventName: string, eventCallback: EventCallback): string => {
const { listenerId } = listenHandle()(eventName, eventCallback);
return listenerId;
}, []);
const listenPrivate = useCallback((eventName: string, eventCallback: EventCallback): string => {
const { listenerId, store } = listenHandle(privateRegisteredEvents)(eventName, eventCallback);
setPrivateRegisteredEvents(store);
return listenerId;
}, [privateRegisteredEvents]);
const unlisten = useCallback((eventName: string, listenerId: string) => unlistenHandle()(eventName, listenerId), []);
const unlistenPrivate = useCallback((eventName: string, listenerId: string) => {
const store = unlistenHandle(privateRegisteredEvents)(eventName, listenerId);
setPrivateRegisteredEvents(store);
}, [privateRegisteredEvents]);
const emit = useCallback((eventName: string, payload: any) => {
emitHandle()(eventName, payload);
}, []);
const emitPrivate = useCallback((eventName: string, payload: any) => {
emitHandle(privateRegisteredEvents)(eventName, payload);
}, [privateRegisteredEvents]);
const removeAllListenersByEvent = useCallback((eventName: string): boolean => removeAllListenersByEventHandle(eventName), []);
useEffect(() => {
return () => setPrivateRegisteredEvents({});
}, []);
return {
listen,
listenPrivate,
emit,
emitPrivate,
unlisten,
unlistenPrivate,
removeAllListenersByEvent,
};
}