Small, readable, almost-tweetable modules utilising classic patterns in modern language.
- Small: PubSub: 127 bytes, EventEmitter: 138 bytes, together: 191 bytes (all gzipped)
- Best practices: Subscribe returns unsubscribe. So you can use anonymous functions.
- Readable: There is nothing magical in the code; except the simplicity.
- Modern: Uses new, yet well-supported features.
- Efficient: No memory leaks, no duplicate calls, no extra looping.
- Clean API:
sub
andpub
(oron
andemit
), need no more, can't go less. - Modular: Use only what you need.
- Typed TypeScript definitions are bundled
Install using yarn
or npm
:
yarn add dead-simple
# or via npm
npm install --save dead-simple
import pubsub from "dead-simple/pubsub";
import eventEmitter from "dead-simple/eventEmitter";
// Alternatively:
// import { pubsub, eventEmitter } from 'dead-simple'
// === PubSub ======
const clicks = pubsub();
const unSub = clicks.sub((target) => console.log(`Clicked on ${target}!`));
clicks.pub("button");
// -> Clicked on button!
unSub();
clicks.pub("link");
// nothing
// === eventEmitter ===
// eventEmitter = named PubSub
const events = eventEmitter();
events.on("click", (target) => console.log(`Clicked on ${target}!`));
const unSubChange = events.on("change", (newValue) =>
console.log(`Value is now ${newValue}!`)
);
events.emit("change", 1968);
// -> Value is now 1968!
unSubChange();
events.emit("change", 1968);
// nothing
events.emit("click", "button");
// -> Clicked on button!
Used ES6: const, arrow functions, Map, Set, object shorthand
Chrome* | Edge | FF | IE | Opera | Safari | iOS | Node |
---|---|---|---|---|---|---|---|
38 | 12 | 13 | -* | 25 | 7.1 | 8 | 4 |
Notes:
- Chrome includes mobile Chrome (Android 4+).
- IE 11 does not support only syntax feature, arrow functions and object shorthand.
- The module needs to be bundled, of course.
This project started a pair of gists which included a hand minified version, too.
We were able to get down to 91B for PubSub:
export default (s = new Set()) => ({
pub: (d) => s.forEach((f) => f(d)),
sub: (f) => s.add(f).delete.bind(s, f),
});
And 139B for EventEmitter (p
is PubSub):
export default (e) => (
(e = new Map()),
Object.freeze({
on: (n, f) => (e.has(name) || e.set(n, p()), e.get(n).sub(f)),
emit: (n, d) => e.has(n) && e.get(n).pub(d),
})
);
These versions are for fun, more like a proof of concept and may not work in some browsers.