@infectedbyjs/emitts
Version:
A type-safe event emitter for TypeScript with priority-based listeners, sequential/parallel execution strategies, and memory leak detection
228 lines (167 loc) • 6.57 kB
Markdown
[](https://github.com/ellerbrock/typescript-badges/)
A type-safe event emitter for TypeScript with priority-based listeners, sequential/parallel execution strategies, and memory leak detection. Provides full type inference for event names and payloads without type casting.
- 🎯 **Fully Type-Safe**: Complete TypeScript support with strict type checking
- ⚡ **High Performance**: Optimized for both small and large-scale applications
- 🎮 **Priority Control**: Execute listeners in order of importance
- 🔄 **Flexible Execution**: Choose between parallel or sequential execution
- 🐛 **Debug Support**: Built-in debugging capabilities
- 🛡️ **Memory Safe**: Memory leak detection with maxListeners warning
- 🔄 **Promise-based API**: Use promises for asynchronous operations
- 🔄 **Zero Dependencies**: No external dependencies
```bash
npm install @infectedbyjs/emitts
```
```typescript
import {EmitTS} from "@infectedbyjs/emitts"
// Define your events
type AppEvents = {
greet: string
data: number
userJoined: {id: number; name: string}
}
// Create type-safe emitter
const emitter = new EmitTS<AppEvents>()
// TypeScript will infer correct types
emitter.on("greet", (name) => {
console.log(`Hello, ${name}!`)
})
emitter.on("userJoined", (user) => {
console.log(`User ${user.name} joined`)
})
// Priority-based listeners
emitter.on("data", () => console.log("Second"), 0)
emitter.on("data", () => console.log("First"), 100)
// Sequential execution
await emitter.emit("data", 42, {strategy: "sequential"})
```
```typescript
emitter.on("dataUpdated", (data) => console.log("Second listener"), 1)
emitter.on("dataUpdated", (data) => console.log("First listener"), 2) // Higher priority
await emitter.emit("dataUpdated", {newValue: "test"})
// Output:
// First listener
// Second listener
```
```typescript
// Sequential execution (one after another)
await emitter.emit("dataUpdated", data, {strategy: "sequential"})
// Parallel execution (default)
await emitter.emit("dataUpdated", data, {strategy: "parallel"})
```
```typescript
// Automatically removes listener after first execution
emitter.once("userLoggedIn", (data) => console.log("This will run only once"))
```
```typescript
// Wait for the next event
const data = await emitter.toPromise("dataUpdated")
console.log("Got data:", data)
```
```typescript
const emitter = new EmitTS<MyEvents>({
debug: true,
logger: (operation, data) => {
console.log(`[DEBUG] ${operation}:`, data)
},
})
```
```typescript
interface EmitTSOptions {
debug?: boolean // Enable debug logging
logger?: DebugLog // Custom debug logger
maxListeners?: number // Max listeners warning threshold (default: 10)
}
```
| Method | Description | Type |
| ---------------- | ---------------------------------- | ------------------------------------------------------------------------------------------- |
| `on` | Subscribe to an event | `(event: keyof Events, callback: EventCallback<Events[K]>, priority?: number) => CleanUpFn` |
| `once` | Subscribe to an event once | `(event: keyof Events, callback: EventCallback<Events[K]>, priority?: number) => void` |
| `off` | Unsubscribe from an event | `(event?: keyof Events, callback?: EventCallback<Events[K]>) => void` |
| `emit` | Emit an event | `(event: keyof Events, data: Events[K], options?: EmitOptions) => Promise<void>` |
| `toPromise` | Convert next event to promise | `(event: keyof Events) => Promise<Events[K]>` |
| `has` | Check if event has listeners | `(event: keyof Events) => boolean` |
| `isEmpty` | Check if emitter has any listeners | `() => boolean` |
| `listenersCount` | Get number of listeners | `(event: keyof Events) => number` |
| `clear` | Remove all listeners | `() => void` |
```typescript
type EventCallback<T> = (data: T) => void | Promise<void>
type EmitOptions = {
strategy?: "parallel" | "sequential"
}
type CleanUpFn = () => void
```
1. **Type Safety**
```typescript
// Define event types for type safety
interface MyEvents {
event1: string
event2: number
}
const emitter = new EmitTS<MyEvents>()
```
2. **Memory Management**
```typescript
// Always clean up listeners
const cleanup = emitter.on("event", handler)
// Later...
cleanup()
```
3. **Error Handling**
```typescript
try {
await emitter.emit("event", data)
} catch (error) {
console.error("Error in event handlers:", error)
}
```
4. **Priority Usage**
```typescript
// Use priorities for critical handlers
emitter.on("critical", handler, 100) // High priority
emitter.on("normal", handler, 0) // Normal priority
```
1. **TypeScript Errors**
```typescript
// ❌ Error: Type 'string' is not assignable to type 'number'
emitter.emit("data", "42") // Wrong type
// ✅ Correct usage
emitter.emit("data", 42) // Correct type
```
2. **Memory Leaks**
```typescript
// ❌ Potential memory leak
emitter.on("event", handler) // No cleanup
// ✅ Proper cleanup
const cleanup = emitter.on("event", handler)
// When done:
cleanup()
```
3. **Async Handler Issues**
```typescript
// ❌ Missing await
emitter.emit("event", data) // Might not wait for handlers
// ✅ Proper async handling
await emitter.emit("event", data) // Waits for all handlers
```
Contributions are welcome! Please feel free to submit a Pull Request.
MIT