fastevent 1.0.4 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc.js +20 -0
- package/.vscode/settings.json +18 -0
- package/CHANGELOG.md +22 -6
- package/dist/devTools.d.mts +308 -0
- package/dist/devTools.d.ts +308 -0
- package/dist/devTools.js +3 -0
- package/dist/devTools.js.map +1 -0
- package/dist/devTools.mjs +3 -0
- package/dist/devTools.mjs.map +1 -0
- package/dist/index.d.mts +40 -17
- package/dist/index.d.ts +40 -17
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/example/README.md +54 -0
- package/example/eslint.config.js +28 -0
- package/example/index.html +13 -0
- package/example/package.json +29 -0
- package/example/pnpm-lock.yaml +2047 -0
- package/example/public/vite.svg +1 -0
- package/example/src/App.css +42 -0
- package/example/src/App.tsx +60 -0
- package/example/src/assets/react.svg +1 -0
- package/example/src/index.css +68 -0
- package/example/src/main.tsx +10 -0
- package/example/src/vite-env.d.ts +1 -0
- package/example/tsconfig.app.json +26 -0
- package/example/tsconfig.json +7 -0
- package/example/tsconfig.node.json +24 -0
- package/example/vite.config.ts +7 -0
- package/package.json +15 -2
- package/readme.md +275 -66
- package/readme_cn.md +275 -70
- package/src/__tests__/emit.test.ts +68 -69
- package/src/__tests__/emitAsync.test.ts +41 -42
- package/src/__tests__/many.test.ts +15 -16
- package/src/__tests__/meta.test.ts +19 -19
- package/src/__tests__/off.test.ts +162 -162
- package/src/__tests__/onany.test.ts +97 -98
- package/src/__tests__/once.test.ts +42 -43
- package/src/__tests__/retain.test.ts +36 -36
- package/src/__tests__/scope.test.ts +38 -39
- package/src/__tests__/types.test.ts +97 -80
- package/src/__tests__/waitFor.test.ts +36 -29
- package/src/__tests__/wildcard.test.ts +114 -115
- package/src/devTools.ts +166 -0
- package/src/event.ts +272 -222
- package/src/scope.ts +64 -55
- package/src/types.ts +38 -34
- package/src/utils/WeakObjectMap.ts +64 -0
- package/tsconfig.json +103 -111
- package/tsup.config.ts +17 -6
package/readme.md
CHANGED
|
@@ -4,9 +4,9 @@ FastEvent is a powerful TypeScript event management library that provides flexib
|
|
|
4
4
|
|
|
5
5
|
Compared to `EventEmitter2`, `FastEvent` has the following advantages:
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
7
|
+
- `FastEvent` performs about `1+` times better than `EventEmitter2` when publishing and subscribing with wildcards.
|
|
8
|
+
- `FastEvent` has a package size of `6.3kb`, while `EventEmitter2` is `43.4kb`.
|
|
9
|
+
- `FastEvent` offers more comprehensive features.
|
|
10
10
|
|
|
11
11
|
# Installation
|
|
12
12
|
|
|
@@ -33,43 +33,67 @@ import { FastEvent } from 'fastevent';
|
|
|
33
33
|
const events = new FastEvent();
|
|
34
34
|
|
|
35
35
|
// Subscribe to event
|
|
36
|
-
events.on('user/login', (
|
|
37
|
-
|
|
36
|
+
events.on('user/login', (message) => {
|
|
37
|
+
console.log('User login:', message.payload);
|
|
38
|
+
console.log('Event type:', message.type);
|
|
39
|
+
console.log('Metadata:', message.meta);
|
|
38
40
|
});
|
|
39
41
|
|
|
40
|
-
// Publish event
|
|
42
|
+
// Publish event - Method 1: Parameters
|
|
41
43
|
events.emit('user/login', { id: 1, name: 'Alice' });
|
|
44
|
+
|
|
45
|
+
// Publish event - Method 2: Message object
|
|
46
|
+
events.emit({
|
|
47
|
+
type: 'user/login',
|
|
48
|
+
payload: { id: 1, name: 'Alice' },
|
|
49
|
+
meta: { timestamp: Date.now() },
|
|
50
|
+
});
|
|
42
51
|
```
|
|
43
52
|
|
|
44
53
|
# Guide
|
|
45
54
|
|
|
55
|
+
## Event Message Format
|
|
56
|
+
|
|
57
|
+
FastEvent uses a standardized message format for all events:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
type FastEventMessage<T = string, P = any, M = unknown> = {
|
|
61
|
+
type: T; // Event type
|
|
62
|
+
payload: P; // Event data
|
|
63
|
+
meta: M; // Event metadata
|
|
64
|
+
};
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Event listeners always receive this message object, providing consistent access to event data and metadata.
|
|
68
|
+
|
|
46
69
|
## Event Wildcards
|
|
47
70
|
|
|
48
71
|
FastEvent supports two types of wildcards:
|
|
49
|
-
|
|
50
|
-
-
|
|
72
|
+
|
|
73
|
+
- `*`: Matches a single path level
|
|
74
|
+
- `**`: Matches multiple path levels
|
|
51
75
|
|
|
52
76
|
```typescript
|
|
53
77
|
const events = new FastEvent();
|
|
54
78
|
|
|
55
79
|
// Matches user/*/login
|
|
56
|
-
events.on('user/*/login', (
|
|
57
|
-
|
|
80
|
+
events.on('user/*/login', (message) => {
|
|
81
|
+
console.log('Any user type login:', message.payload);
|
|
58
82
|
});
|
|
59
83
|
|
|
60
84
|
// Matches all events under user
|
|
61
|
-
events.on('user/**', (
|
|
62
|
-
|
|
85
|
+
events.on('user/**', (message) => {
|
|
86
|
+
console.log('All user-related events:', message.payload);
|
|
63
87
|
});
|
|
64
88
|
|
|
65
89
|
// Trigger events
|
|
66
|
-
events.emit('user/admin/login', { id: 1 });
|
|
67
|
-
events.emit('user/admin/profile/update', { name: 'New' });
|
|
90
|
+
events.emit('user/admin/login', { id: 1 }); // Both handlers will be called
|
|
91
|
+
events.emit('user/admin/profile/update', { name: 'New' }); // Only ** handler will be called
|
|
68
92
|
```
|
|
69
93
|
|
|
70
94
|
## Event Scoping
|
|
71
95
|
|
|
72
|
-
Scopes allow you to handle events within specific namespaces:
|
|
96
|
+
Scopes allow you to handle events within specific namespaces. Note that scopes share the same listener table with the parent emitter:
|
|
73
97
|
|
|
74
98
|
```typescript
|
|
75
99
|
const events = new FastEvent();
|
|
@@ -77,13 +101,59 @@ const events = new FastEvent();
|
|
|
77
101
|
// Create user-related scope
|
|
78
102
|
const userScope = events.scope('user');
|
|
79
103
|
|
|
80
|
-
//
|
|
81
|
-
userScope.on('login',
|
|
82
|
-
|
|
83
|
-
|
|
104
|
+
// These are equivalent:
|
|
105
|
+
userScope.on('login', handler);
|
|
106
|
+
events.on('user/login', handler);
|
|
107
|
+
|
|
108
|
+
// These are also equivalent:
|
|
109
|
+
userScope.emit('login', data);
|
|
110
|
+
events.emit('user/login', data);
|
|
111
|
+
|
|
112
|
+
// Clear all listeners in the scope
|
|
113
|
+
userScope.offAll(); // Equivalent to events.offAll('user')
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Listener Options
|
|
117
|
+
|
|
118
|
+
When subscribing to events, you can specify additional options:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
interface FastEventListenOptions {
|
|
122
|
+
// Number of times the listener should be called (0 for unlimited, 1 for once)
|
|
123
|
+
count?: number;
|
|
124
|
+
// Add the listener to the beginning of the listeners array
|
|
125
|
+
prepend?: boolean;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Example: Listen for first 3 occurrences
|
|
129
|
+
events.on('data', handler, { count: 3 });
|
|
130
|
+
|
|
131
|
+
// Example: Ensure handler is called before other listeners
|
|
132
|
+
events.on('important', handler, { prepend: true });
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Removing Listeners
|
|
136
|
+
|
|
137
|
+
FastEvent provides multiple ways to remove listeners:
|
|
84
138
|
|
|
85
|
-
|
|
86
|
-
|
|
139
|
+
```typescript
|
|
140
|
+
// Remove specific listener
|
|
141
|
+
events.off(listener);
|
|
142
|
+
|
|
143
|
+
// Remove all listeners for an event
|
|
144
|
+
events.off('user/login');
|
|
145
|
+
|
|
146
|
+
// Remove specific listener for an event
|
|
147
|
+
events.off('user/login', listener);
|
|
148
|
+
|
|
149
|
+
// Remove all listeners with wildcard pattern
|
|
150
|
+
events.off('user/*');
|
|
151
|
+
|
|
152
|
+
// Remove all listeners
|
|
153
|
+
events.offAll();
|
|
154
|
+
|
|
155
|
+
// Remove all listeners under a prefix
|
|
156
|
+
events.offAll('user');
|
|
87
157
|
```
|
|
88
158
|
|
|
89
159
|
## One-time Events
|
|
@@ -94,11 +164,11 @@ Use `once` to subscribe to events that trigger only once:
|
|
|
94
164
|
const events = new FastEvent();
|
|
95
165
|
|
|
96
166
|
events.once('startup', () => {
|
|
97
|
-
|
|
167
|
+
console.log('Application started');
|
|
98
168
|
});
|
|
99
169
|
|
|
100
|
-
|
|
101
|
-
events.
|
|
170
|
+
// Equivalent to:
|
|
171
|
+
events.on('startup', handler, { count: 1 });
|
|
102
172
|
```
|
|
103
173
|
|
|
104
174
|
## Asynchronous Events
|
|
@@ -109,15 +179,42 @@ Support for asynchronous event handling:
|
|
|
109
179
|
const events = new FastEvent();
|
|
110
180
|
|
|
111
181
|
events.on('data/fetch', async () => {
|
|
112
|
-
|
|
113
|
-
|
|
182
|
+
const response = await fetch('https://api.example.com/data');
|
|
183
|
+
return await response.json();
|
|
114
184
|
});
|
|
115
185
|
|
|
116
|
-
// Async event publishing
|
|
186
|
+
// Async event publishing returns array of results/errors
|
|
117
187
|
const results = await events.emitAsync('data/fetch');
|
|
118
188
|
console.log('Results from all handlers:', results);
|
|
119
189
|
```
|
|
120
190
|
|
|
191
|
+
## Listener Return Values
|
|
192
|
+
|
|
193
|
+
Both `emit` and `emitAsync` methods return the results from all event listeners:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
const events = new FastEvent();
|
|
197
|
+
|
|
198
|
+
// Synchronous listeners with return values
|
|
199
|
+
events.on('calculate', () => 1);
|
|
200
|
+
events.on('calculate', () => 2);
|
|
201
|
+
events.on('calculate', () => 3);
|
|
202
|
+
|
|
203
|
+
// Get array of return values
|
|
204
|
+
const results = events.emit('calculate');
|
|
205
|
+
console.log('Results:', results); // [1, 2, 3]
|
|
206
|
+
|
|
207
|
+
// Asynchronous listeners
|
|
208
|
+
events.on('process', async () => 'result 1');
|
|
209
|
+
events.on('process', async () => 'result 2');
|
|
210
|
+
|
|
211
|
+
// Get array of resolved values/errors
|
|
212
|
+
const asyncResults = await events.emitAsync('process');
|
|
213
|
+
console.log('Async results:', asyncResults); // ['result 1', 'result 2']
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
For asynchronous events, `emitAsync` will wait for all listeners to complete and return an array containing either the resolved values or error objects if a listener fails.
|
|
217
|
+
|
|
121
218
|
## Event Waiting
|
|
122
219
|
|
|
123
220
|
Use `waitFor` to wait for specific events:
|
|
@@ -126,13 +223,13 @@ Use `waitFor` to wait for specific events:
|
|
|
126
223
|
const events = new FastEvent();
|
|
127
224
|
|
|
128
225
|
async function waitForLogin() {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
226
|
+
try {
|
|
227
|
+
// Wait for login event with 5 seconds timeout
|
|
228
|
+
const userData = await events.waitFor('user/login', 5000);
|
|
229
|
+
console.log('User logged in:', userData);
|
|
230
|
+
} catch (error) {
|
|
231
|
+
console.log('Login wait timeout');
|
|
232
|
+
}
|
|
136
233
|
}
|
|
137
234
|
|
|
138
235
|
waitForLogin();
|
|
@@ -151,8 +248,8 @@ const events = new FastEvent();
|
|
|
151
248
|
events.emit('config/update', { theme: 'dark' }, true);
|
|
152
249
|
|
|
153
250
|
// Later subscribers will immediately receive the retained data
|
|
154
|
-
events.on('config/update', (
|
|
155
|
-
|
|
251
|
+
events.on('config/update', (message) => {
|
|
252
|
+
console.log('Config:', message.payload); // Immediately outputs: Config: { theme: 'dark' }
|
|
156
253
|
});
|
|
157
254
|
```
|
|
158
255
|
|
|
@@ -164,7 +261,7 @@ By default, '/' is used as the event path delimiter, but you can use custom deli
|
|
|
164
261
|
|
|
165
262
|
```typescript
|
|
166
263
|
const events = new FastEvent({
|
|
167
|
-
|
|
264
|
+
delimiter: '.',
|
|
168
265
|
});
|
|
169
266
|
```
|
|
170
267
|
|
|
@@ -175,12 +272,12 @@ Use `onAny` to listen to all events:
|
|
|
175
272
|
```typescript
|
|
176
273
|
const events = new FastEvent();
|
|
177
274
|
|
|
178
|
-
events.onAny((
|
|
179
|
-
|
|
275
|
+
events.onAny((message) => {
|
|
276
|
+
console.log(`Event ${message.type} triggered:`, message.payload);
|
|
180
277
|
});
|
|
181
278
|
|
|
182
|
-
|
|
183
|
-
events.
|
|
279
|
+
// Can also use prepend option
|
|
280
|
+
events.onAny(handler, { prepend: true });
|
|
184
281
|
```
|
|
185
282
|
|
|
186
283
|
## Metadata (Meta)
|
|
@@ -193,15 +290,15 @@ Set global metadata when creating a FastEvent instance:
|
|
|
193
290
|
|
|
194
291
|
```typescript
|
|
195
292
|
const events = new FastEvent({
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
293
|
+
meta: {
|
|
294
|
+
version: '1.0',
|
|
295
|
+
environment: 'production',
|
|
296
|
+
},
|
|
200
297
|
});
|
|
201
298
|
|
|
202
|
-
events.on('user/login', (
|
|
203
|
-
|
|
204
|
-
|
|
299
|
+
events.on('user/login', (message) => {
|
|
300
|
+
console.log('Event data:', message.payload);
|
|
301
|
+
console.log('Metadata:', message.meta); // Contains type, version, and environment
|
|
205
302
|
});
|
|
206
303
|
```
|
|
207
304
|
|
|
@@ -211,20 +308,21 @@ Additional metadata can be passed when publishing events, which will be merged w
|
|
|
211
308
|
|
|
212
309
|
```typescript
|
|
213
310
|
const events = new FastEvent({
|
|
214
|
-
|
|
311
|
+
meta: { app: 'MyApp' },
|
|
215
312
|
});
|
|
216
313
|
|
|
217
314
|
// Add specific metadata when publishing event
|
|
218
|
-
events.emit(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
315
|
+
events.emit(
|
|
316
|
+
'order/create',
|
|
317
|
+
{ orderId: '123' }, // Event data
|
|
318
|
+
false, // Don't retain
|
|
319
|
+
{ timestamp: Date.now() }, // Event-specific metadata
|
|
222
320
|
);
|
|
223
321
|
|
|
224
322
|
// Listener receives merged metadata
|
|
225
|
-
events.on('order/create', (
|
|
226
|
-
|
|
227
|
-
|
|
323
|
+
events.on('order/create', (message) => {
|
|
324
|
+
console.log('Order:', message.payload); // { orderId: '123' }
|
|
325
|
+
console.log('Metadata:', message.meta); // { type: 'order/create', app: 'MyApp', timestamp: ... }
|
|
228
326
|
});
|
|
229
327
|
```
|
|
230
328
|
|
|
@@ -234,20 +332,114 @@ FastEvent provides error handling mechanisms:
|
|
|
234
332
|
|
|
235
333
|
```typescript
|
|
236
334
|
const events = new FastEvent({
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
335
|
+
ignoreErrors: true, // Default is true, won't throw errors
|
|
336
|
+
onListenerError: (type, error) => {
|
|
337
|
+
console.error(`Error handling event ${type}:`, error);
|
|
338
|
+
},
|
|
241
339
|
});
|
|
242
340
|
|
|
243
341
|
events.on('process', () => {
|
|
244
|
-
|
|
342
|
+
throw new Error('Processing failed');
|
|
245
343
|
});
|
|
246
344
|
|
|
247
345
|
// Won't throw error, will trigger onListenerError instead
|
|
248
346
|
events.emit('process');
|
|
249
347
|
```
|
|
250
348
|
|
|
349
|
+
## Generic Parameters
|
|
350
|
+
|
|
351
|
+
FastEvent supports three generic type parameters for precise type control:
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
class FastEvent<
|
|
355
|
+
Events extends Record<string, any> = Record<string, any>,
|
|
356
|
+
Meta extends Record<string, any> = Record<string, any>,
|
|
357
|
+
Types extends keyof Events = keyof Events
|
|
358
|
+
>
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
1. `Events`: Defines the mapping between event types and their payload types
|
|
362
|
+
2. `Meta`: Defines the type of metadata that can be attached to events
|
|
363
|
+
3. `Types`: The union type of all event types (usually inferred from Events)
|
|
364
|
+
|
|
365
|
+
### Basic Type Safety
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
// Define event types
|
|
369
|
+
interface MyEvents {
|
|
370
|
+
'user/login': { id: number; name: string };
|
|
371
|
+
'user/logout': { id: number };
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Create typed event emitter
|
|
375
|
+
const events = new FastEvent<MyEvents>();
|
|
376
|
+
|
|
377
|
+
// Type checking for event names and payload
|
|
378
|
+
events.on('user/login', (message) => {
|
|
379
|
+
// message.payload is typed as { id: number; name: string }
|
|
380
|
+
const { id, name } = message.payload;
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// Error: wrong event name
|
|
384
|
+
events.emit('wrong/event', {});
|
|
385
|
+
|
|
386
|
+
// Error: wrong payload type
|
|
387
|
+
events.emit('user/login', { wrong: 'type' });
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Custom Metadata Types
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
// Define metadata structure
|
|
394
|
+
interface MyMeta {
|
|
395
|
+
timestamp: number;
|
|
396
|
+
source: string;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Define events with custom metadata
|
|
400
|
+
const events = new FastEvent<MyEvents, MyMeta>();
|
|
401
|
+
|
|
402
|
+
events.on('user/login', (message) => {
|
|
403
|
+
// message.meta is typed as MyMeta
|
|
404
|
+
const { timestamp, source } = message.meta;
|
|
405
|
+
console.log(`Login from ${source} at ${timestamp}`);
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
// Emit with typed metadata
|
|
409
|
+
events.emit('user/login', { id: 1, name: 'Alice' }, false, { timestamp: Date.now(), source: 'web' });
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Advanced Type Usage
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
// Define events with different payload types
|
|
416
|
+
interface ComplexEvents {
|
|
417
|
+
'data/number': number;
|
|
418
|
+
'data/string': string;
|
|
419
|
+
'data/object': { value: any };
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const events = new FastEvent<ComplexEvents>();
|
|
423
|
+
|
|
424
|
+
// TypeScript ensures type safety for each event
|
|
425
|
+
events.on('data/number', (message) => {
|
|
426
|
+
const sum = message.payload + 1; // payload is typed as number
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
events.on('data/string', (message) => {
|
|
430
|
+
const upper = message.payload.toUpperCase(); // payload is typed as string
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
events.on('data/object', (message) => {
|
|
434
|
+
const value = message.payload.value; // payload is typed as { value: any }
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
// All emissions are type checked
|
|
438
|
+
events.emit('data/number', 42);
|
|
439
|
+
events.emit('data/string', 'hello');
|
|
440
|
+
events.emit('data/object', { value: true });
|
|
441
|
+
```
|
|
442
|
+
|
|
251
443
|
## Custom Options
|
|
252
444
|
|
|
253
445
|
The FastEvent constructor supports multiple options:
|
|
@@ -255,18 +447,18 @@ The FastEvent constructor supports multiple options:
|
|
|
255
447
|
```typescript
|
|
256
448
|
const events = new FastEvent({
|
|
257
449
|
// Event path delimiter, default is '/'
|
|
258
|
-
delimiter: '.',
|
|
450
|
+
delimiter: '.',
|
|
259
451
|
// Context for event handlers
|
|
260
|
-
context: null,
|
|
452
|
+
context: null,
|
|
261
453
|
// Metadata, passed to all event handlers
|
|
262
454
|
meta: { ... },
|
|
263
|
-
|
|
455
|
+
|
|
264
456
|
// Error handling
|
|
265
457
|
ignoreErrors: true,
|
|
266
458
|
onListenerError: (type, error) => {
|
|
267
459
|
console.error(`Event error:`, type, error);
|
|
268
460
|
},
|
|
269
|
-
|
|
461
|
+
|
|
270
462
|
// Callbacks for listener addition/removal
|
|
271
463
|
onAddListener: (path, listener) => {
|
|
272
464
|
console.log('Listener added:', path);
|
|
@@ -274,9 +466,26 @@ const events = new FastEvent({
|
|
|
274
466
|
onRemoveListener: (path, listener) => {
|
|
275
467
|
console.log('Listener removed:', path);
|
|
276
468
|
}
|
|
469
|
+
onClearListeners: () => {
|
|
470
|
+
console.log('清空监听器:', path);
|
|
471
|
+
},
|
|
472
|
+
onExecuteListener: (message: FastEventMessage, returns: any[], listeners: (FastEventListener<any, any, any> | [FastEventListener<any, any>, number])[]) => {
|
|
473
|
+
console.log('监听器执行后的回调:');
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### debug
|
|
479
|
+
|
|
480
|
+
Use `debug` option to enable debug mode and import `fastevent/devtools`, so that you can see the events in `Redux Dev Tools`.
|
|
481
|
+
|
|
482
|
+
```ts
|
|
483
|
+
import 'fastevent/devtools';
|
|
484
|
+
const emitter = new FastEvent({
|
|
485
|
+
debug: true,
|
|
277
486
|
});
|
|
278
487
|
```
|
|
279
488
|
|
|
280
489
|
# Performance
|
|
281
490
|
|
|
282
|
-

|
|
491
|
+

|