Skip to content

Commit 42466b1

Browse files
committed
feat: error handler
1 parent 3f791e1 commit 42466b1

File tree

3 files changed

+79
-20
lines changed

3 files changed

+79
-20
lines changed

.eslintrc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
{
2-
"extends": "@so1ve"
2+
"extends": "@so1ve",
3+
"rules": {
4+
"etc/no-implicit-any-catch": "off"
5+
}
36
}

src/index.ts

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export type EventMap = Record<string | symbol, any[]>;
22

3-
export type Listener<A extends any[]> = (...args: A) => void;
3+
export type Listener<A extends any[]> = (...args: A) => void | Promise<void>;
44

55
type _WildcardListener<
66
EM extends EventMap,
@@ -13,9 +13,18 @@ export type ListenerMap<EM extends EventMap> = Map<
1313
Set<Listener<EM[keyof EM]>>
1414
>;
1515

16+
export interface LiteEmitOptions {
17+
errorHandler?: (msg: string) => void;
18+
}
19+
1620
export class LiteEmit<EM extends EventMap = EventMap> {
17-
private listenerMap = new Map() as ListenerMap<EM>;
18-
private wildcardListeners = new Set<WildcardListener<EM>>();
21+
#listenerMap = new Map() as ListenerMap<EM>;
22+
#wildcardListeners = new Set<WildcardListener<EM>>();
23+
#errorHandler: ((msg: string) => void) | undefined;
24+
25+
constructor(options?: LiteEmitOptions) {
26+
this.#errorHandler = options?.errorHandler;
27+
}
1928

2029
on(event: "*", listener: WildcardListener<EM>): this;
2130
on<K extends keyof EM>(event: K, listener: Listener<EM[K]>): this;
@@ -24,14 +33,14 @@ export class LiteEmit<EM extends EventMap = EventMap> {
2433
listener: Listener<EM[K]> | WildcardListener<EM>,
2534
): this {
2635
if (event === "*") {
27-
this.wildcardListeners.add(listener as WildcardListener<EM>);
36+
this.#wildcardListeners.add(listener as WildcardListener<EM>);
2837

2938
return this;
3039
}
31-
if (!this.listenerMap.has(event)) {
32-
this.listenerMap.set(event, new Set());
40+
if (!this.#listenerMap.has(event)) {
41+
this.#listenerMap.set(event, new Set());
3342
}
34-
this.listenerMap.get(event)!.add(listener as any);
43+
this.#listenerMap.get(event)!.add(listener as any);
3544

3645
return this;
3746
}
@@ -51,12 +60,30 @@ export class LiteEmit<EM extends EventMap = EventMap> {
5160
}
5261

5362
emit<K extends keyof EM>(event: K, ...args: EM[K]): this {
54-
if (this.listenerMap.has(event)) {
55-
for (const listener of this.wildcardListeners) {
56-
listener(event, ...args);
63+
if (this.#listenerMap.has(event)) {
64+
for (const listener of this.#wildcardListeners) {
65+
try {
66+
const result = listener(event, ...args);
67+
if (result instanceof Promise) {
68+
result.catch((e) => {
69+
this.#errorHandler?.(e.message);
70+
});
71+
}
72+
} catch (e: any) {
73+
this.#errorHandler?.(e.message);
74+
}
5775
}
58-
for (const listener of this.listenerMap.get(event)!) {
59-
listener(...args);
76+
for (const listener of this.#listenerMap.get(event)!) {
77+
try {
78+
const result = listener(...args);
79+
if (result instanceof Promise) {
80+
result.catch((e) => {
81+
this.#errorHandler?.(e.message);
82+
});
83+
}
84+
} catch (e: any) {
85+
this.#errorHandler?.(e.message);
86+
}
6087
}
6188
}
6289

@@ -71,27 +98,27 @@ export class LiteEmit<EM extends EventMap = EventMap> {
7198
listener?: Listener<EM[K]> | WildcardListener<EM>,
7299
): this {
73100
if (event === undefined) {
74-
this.listenerMap.clear();
75-
this.wildcardListeners.clear();
101+
this.#listenerMap.clear();
102+
this.#wildcardListeners.clear();
76103

77104
return this;
78105
// Event param is given
79106
} else if (event === "*") {
80107
// Remove the specified listener
81108
if (listener) {
82-
this.wildcardListeners.delete(listener as WildcardListener<EM>);
109+
this.#wildcardListeners.delete(listener as WildcardListener<EM>);
83110
// Clear all wildcard listners
84111
} else {
85-
this.wildcardListeners.clear();
112+
this.#wildcardListeners.clear();
86113
}
87114

88115
return this;
89116
}
90117
// The event param is defined and not a wildcard symbol
91118
if (listener) {
92-
this.listenerMap.get(event)?.delete(listener as any);
119+
this.#listenerMap.get(event)?.delete(listener as any);
93120
} else {
94-
this.listenerMap.get(event)?.clear();
121+
this.#listenerMap.get(event)?.clear();
95122
}
96123

97124
return this;

test/index.test.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,15 @@ type EventMap = {
88
bar: ["bar", number, symbol];
99
baz: [42];
1010
faq: [];
11+
error: [];
12+
error2: [];
1113
};
1214

13-
const emitter = new LiteEmit<EventMap>();
15+
const errorMsgs: string[] = [];
16+
17+
const emitter = new LiteEmit<EventMap>({
18+
errorHandler: (s) => errorMsgs.push(s),
19+
});
1420

1521
const Sym = Symbol("d");
1622

@@ -120,4 +126,27 @@ describe("should", () => {
120126

121127
expect(count2).toBe(3);
122128
});
129+
130+
it("errorHandler", () => {
131+
emitter
132+
.on("error", () => {
133+
throw new Error("Foo");
134+
})
135+
.emit("error");
136+
137+
expect(errorMsgs[0]).toBe("Foo");
138+
});
139+
140+
it("errorHandler async", () => {
141+
emitter
142+
.on("error2", async () => {
143+
throw new Error("Bar");
144+
})
145+
.emit("error2");
146+
147+
// Wait for async action
148+
setTimeout(() => {
149+
expect(errorMsgs[1]).toBe("Bar");
150+
}, 500);
151+
});
123152
});

0 commit comments

Comments
 (0)