Skip to content

Commit 630ded4

Browse files
committed
Big refactoring with better types, ES2015+ and smaller size
1 parent fdc729c commit 630ded4

11 files changed

+566
-2524
lines changed

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,3 @@ node_modules/
22
yarn-error.log
33

44
coverage/
5-
api.md

README.md

+68-21
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@
22

33
Simple and tiny event emitter library for JavaScript.
44

5-
* Only **103 bytes** (minified and gzipped).
5+
* Only **78 bytes** (minified and gzipped).
66
It uses [Size Limit] to control size.
77
* `on` method returns `unbind` function. You don’t need to save
88
callback to variable for `removeListener`.
9+
* TypeScript and ES modules support.
910
* No aliases, just `emit` and `on` methods.
1011
No Node.js [EventEmitter] compatibility.
1112

1213
```js
13-
import NanoEvents from 'nanoevents'
14-
const emitter = new NanoEvents()
14+
const createNanoEvents = require('nanoevents')
15+
16+
const emitter = createNanoEvents()
1517

1618
const unbind = emitter.on('tick', volume => {
1719
summary += volume
@@ -34,17 +36,69 @@ summary //=> 2
3436
</a>
3537

3638

37-
## Usage
39+
## Table of Contents
40+
41+
* [TypeScript](#typescript)
42+
* [ES Modules](#es-modules)
43+
* [Mixing to Object](#mixing-to-object)
44+
* [Add Listener](#add-listener)
45+
* [Remove Listener](#remove-listener)
46+
* [Execute Listeners](#execute-listeners)
47+
* [Events List](#events-list)
48+
* [Once](#once)
49+
* [Remove All Listeners](#remove-all-listeners)
50+
51+
52+
## TypeScript
53+
54+
Nano Events accepts interface with event name
55+
to listener argument types mapping.
56+
57+
```ts
58+
import createNanoEvents = require('..')
59+
60+
interface Events {
61+
'set': (name: string, count: number) => void,
62+
'tick': () => void
63+
}
64+
65+
const emitter = createNanoEvents<Events>()
66+
67+
// Correct calls:
68+
emitter.emit('set', 'prop', 1)
69+
emitter.emit('tick')
70+
71+
// Compilation errors:
72+
emitter.emit('set', 'prop', '1')
73+
emitter.emit('tick', 2)
74+
```
75+
3876

39-
### Mixing to Object
77+
## ES Modules
78+
79+
In Node.js 13 you can import ES module by manually added `index.mjs`.
80+
81+
```js
82+
import createNanoEvents from 'nanoevents/index.mjs'
83+
```
84+
85+
For quick hacks you can load Nano Events from CDN. Do not use it in production
86+
because of low performance.
87+
88+
```js
89+
import createNanoEvents from 'https://cdn.jsdelivr.net/npm/nanoevents/index.mjs'
90+
```
91+
92+
93+
## Mixing to Object
4094

4195
Because Nano Events API has only just 2 methods,
4296
you could just create proxy methods in your class.
4397

4498
```js
4599
class Ticker {
46100
constructor() {
47-
this.emitter = new NanoEvents()
101+
this.emitter = createNanoEvents()
48102
}
49103
on() {
50104
return this.emitter.on.apply(this.emitter, arguments)
@@ -55,10 +109,8 @@ class Ticker {
55109
}
56110
```
57111

58-
It allows you to have custom JSDoc or type definitions.
59112

60-
61-
### Add Listener
113+
## Add Listener
62114

63115
Use `on` method to add listener for specific event:
64116

@@ -93,7 +145,7 @@ Note: binding with use of the `.bind()` method won’t work as you might expect
93145
and therefore is not recommended.
94146

95147

96-
### Remove Listener
148+
## Remove Listener
97149

98150
Methods `on` returns `unbind` function. Call it and this listener
99151
will be removed from event.
@@ -112,7 +164,7 @@ emitter.emit('tick', 2)
112164
```
113165

114166

115-
### Execute Listeners
167+
## Execute Listeners
116168

117169
Method `emit` will execute all listeners. First argument is event name, others
118170
will be passed to listeners.
@@ -126,7 +178,7 @@ emitter.emit('tick', 1, 'one')
126178
```
127179

128180

129-
### Events List
181+
## Events List
130182

131183
You can get used events list by `events` property.
132184

@@ -136,15 +188,15 @@ emitter.events //=> { tick: [ [Function] ] }
136188
```
137189

138190

139-
### Once
191+
## Once
140192

141193
If you need add event listener only for first event dispatch,
142194
you can use this snippet:
143195

144196
```js
145197
class Ticker {
146198
constructor() {
147-
this.emitter = new NanoEvents()
199+
this.emitter = createNanoEvents()
148200
}
149201
150202
once (event, callback) {
@@ -157,17 +209,12 @@ class Ticker {
157209
}
158210
```
159211

160-
### Remove all listeners
161212

162-
`unbindAll` method will remove all listeners to all events.
213+
## Remove All Listeners
163214

164215
```js
165-
import unbindAll from 'nanoevents/unbind-all';
166-
167216
emitter.on('event1', () => { })
168217
emitter.on('event2', () => { })
169218

170-
unbindAll(emitter);
171-
172-
Object.keys(emitter.events) //=> { }
219+
emitter.events = { }
173220
```

index.d.ts

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
interface EventsMap {
2+
[event: string]: any
3+
}
4+
5+
interface DefaultEvents extends EventsMap {
6+
[event: string]: (...args: any) => void
7+
}
8+
9+
declare class Emitter<Events extends EventsMap> {
10+
/**
11+
* Event names in keys and arrays with listeners in values.
12+
*
13+
* ```js
14+
* emitter1.events = emitter2.events
15+
* emitter2.events = { }
16+
* ```
17+
*/
18+
events: Partial<{ [E in keyof Events]: Events[E][] }>
19+
20+
/**
21+
* Add a listener for a given event.
22+
*
23+
* ```js
24+
* const unbind = ee.on('tick', (tickType, tickDuration) => {
25+
* count += 1
26+
* })
27+
*
28+
* disable () {
29+
* unbind()
30+
* }
31+
* ```
32+
*
33+
* @param event The event name.
34+
* @param cb The listener function.
35+
* @returns Unbind listener from event.
36+
*/
37+
on <K extends keyof Events>(event: K, cb: Events[K]): () => void
38+
39+
/**
40+
* Calls each of the listeners registered for a given event.
41+
*
42+
* ```js
43+
* ee.emit('tick', tickType, tickDuration)
44+
* ```
45+
*
46+
* @param event The event name.
47+
* @param args The arguments for listeners.
48+
*/
49+
emit <K extends keyof Events>(
50+
event: K,
51+
...args: Parameters<Events[K]>
52+
): void
53+
}
54+
55+
/**
56+
* Create event emitter.
57+
*
58+
* ```js
59+
* import createNanoEvents from 'nanoevents'
60+
*
61+
* class Ticker {
62+
* constructor() {
63+
* this.emitter = createNanoEvents()
64+
* }
65+
* on(...args) {
66+
* return this.emitter.on(...args)
67+
* }
68+
* tick() {
69+
* this.emitter.emit('tick')
70+
* }
71+
* }
72+
* ```
73+
*/
74+
declare function createNanoEvents<Events extends EventsMap = DefaultEvents> (
75+
): Emitter<Events>
76+
77+
export = createNanoEvents

index.js

+12-86
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,18 @@
1-
(
2-
/**
3-
* Interface for event subscription.
4-
*
5-
* @example
6-
* var NanoEvents = require('nanoevents')
7-
*
8-
* class Ticker {
9-
* constructor() {
10-
* this.emitter = new NanoEvents()
11-
* }
12-
* on() {
13-
* return this.emitter.on.apply(this.events, arguments)
14-
* }
15-
* tick() {
16-
* this.emitter.emit('tick')
17-
* }
18-
* }
19-
*
20-
* @alias NanoEvents
21-
* @class
22-
*/
23-
module.exports = function NanoEvents () {
24-
/**
25-
* Event names in keys and arrays with listeners in values.
26-
* @type {object}
27-
*
28-
* @example
29-
* Object.keys(ee.events)
30-
*
31-
* @alias NanoEvents#events
32-
*/
33-
this.events = { }
1+
module.exports = function () {
2+
let emitter = {
3+
events: { }
344
}
35-
).prototype = {
365

37-
/**
38-
* Calls each of the listeners registered for a given event.
39-
*
40-
* @param {string} event The event name.
41-
* @param {...*} arguments The arguments for listeners.
42-
*
43-
* @return {undefined}
44-
*
45-
* @example
46-
* ee.emit('tick', tickType, tickDuration)
47-
*
48-
* @alias NanoEvents#emit
49-
* @method
50-
*/
51-
emit: function emit (event) {
52-
var args = [].slice.call(arguments, 1)
53-
// Array.prototype.call() returns empty array if context is not array-like
54-
;[].slice.call(this.events[event] || []).filter(function (i) {
55-
i.apply(null, args)
56-
})
57-
},
58-
59-
/**
60-
* Add a listener for a given event.
61-
*
62-
* @param {string} event The event name.
63-
* @param {function} cb The listener function.
64-
*
65-
* @return {function} Unbind listener from event.
66-
*
67-
* @example
68-
* const unbind = ee.on('tick', (tickType, tickDuration) => {
69-
* count += 1
70-
* })
71-
*
72-
* disable () {
73-
* unbind()
74-
* }
75-
*
76-
* @alias NanoEvents#on
77-
* @method
78-
*/
79-
on: function on (event, cb) {
80-
if (process.env.NODE_ENV !== 'production' && typeof cb !== 'function') {
81-
throw new Error('Listener must be a function')
82-
}
83-
84-
(this.events[event] = this.events[event] || []).push(cb)
6+
emitter.emit = (event, ...args) => {
7+
(emitter.events[event] || []).filter(i => i(...args))
8+
}
859

10+
emitter.on = (event, cb) => {
11+
(emitter.events[event] = emitter.events[event] || []).push(cb)
8612
return function () {
87-
this.events[event] = this.events[event].filter(function (i) {
88-
return i !== cb
89-
})
90-
}.bind(this)
13+
emitter.events[event] = emitter.events[event].filter(i => i !== cb)
14+
}
9115
}
16+
17+
return emitter
9218
}

0 commit comments

Comments
 (0)