pub-sub-es
Version:
A simple pub-sub service
133 lines (84 loc) • 6.41 kB
Markdown
//img.shields.io/npm/v/pub-sub-es.svg)](https://www.npmjs.com/package/pub-sub-es)
[](https://nodejs.org/api/documentation.html#documentation_stability_index)
[](https://github.com/flekschas/pub-sub/actions?query=workflow%3Abuild)
[](https://unpkg.com/pub-sub-es)
[](https://github.com/prettier/prettier)
[](http://pub-sub.lekschas.de)
> A [tiny <1KB](https://bundlephobia.com/result?p=pub-sub-es) [pub-sub](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern)-based event library that lets you send custom message within and cross the window! It's written in ES6 and makes use of the awesome [Broadcast Channel API](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API).
**Demo:** [pub-sub.lekschas.de](http://pub-sub.lekschas.de)
```
npm -i -D pub-sub-es
```
```javascript
import createPubSub from 'pub-sub-es';
// Creates a new pub-sub event listener stack.
const pubSub = createPubSub();
// Subscribe to an event
const myEmojiEventHandler = (msg) => console.log(`🎉 ${msg} 😍`);
pubSub.subscribe('my-emoji-event', myEmojiEventHandler);
// Publish an event
pubSub.publish('my-emoji-event', 'Yuuhuu'); // >> 🎉 Yuuhuu 😍
// Unsubscribe
pubSub.unsubscribe('my-emoji-event', myEmojiEventHandler);
```
By default, `pub-sub` assumes you are publishing any kind of events with an
unknown payload. With TypeScript you can specify which events (name and payload)
you are publishing as follows.
```typescript
import createPubSub, { Event } from 'pub-sub-es';
type Events = Event<'init' | 'destroy', undefined> &
Event<'solution', number> &
Event<'selection', number[]>;
const pubSub = createPubSub<Events>();
```
With this, we established that `pubSub` will handle four events:
- `init` and `destroy` feature no payload (i.e., the payload is `undefined`)
- `solution` features a single `number` as payload
- `selection` features an array of numbers as payload
When you listen to an event, the payload will now be typed. I.e.:
```typescript
pubSub.subscribe('solution', (payload) => console.log(payload + 2));
pubSub.publish('solution', 42); // => ✅
pubSub.publish('solution', '42'); // => ❌
```
`pub-sub-es` exports the factory function (`createPubSub`) for creating a new pub-sub service by default and a global pub-sub service (`globalPubSub`). The API is the same for both.
#### `createPubSub(options = { async: false, caseInsensitive: false, stack: { __times__: {} })`
> Creates a new pub-sub instances
**Arguments:**
- `options` is an object for customizing pubSub. The following properties are understood:
- `async`: when `true`, events are published asynchronously to decouple the process of the originator and consumer.
- `caseInsensitive`: when `true`, event names are case insensitive
- `stack`: is an object holding the event listeners and defaults to a new stack when being omitted.
**Returns:** a new pub-sub service
#### `pubSub.publish(event, news, options = { async: false, isNoGlobalBroadcast: false})`
> Publishes or broadcasts an event with some news or payload
**Arguments:**
- `event` is the name of the event to be published.
- `news` is an arbitrary value that is being broadcasted.
- `options` is an object for customizing the behavior. The following properties are understood:
- `async`: overrides the global `async` flag for a single call.
- `isNoGlobalBroadcast`: overrides the global `isGlobal` flag for a single call.
#### `pubSub.subscribe(event, handler, times)`
> Subscribes a handler to a specific event
- `event` is the name of the event to be published.
- `handler` is the handler function that is being called together with the broadcasted value.
- `times` is the number of times the handler is invoked before it's automatically unsubscribed.
**Returns:** an object of form `{ event, handler }`. This object can be used to automatically unsubscribe, e.g., `pubSub.unsubscribe(pubSub.subscribe('my-event', myHandler))`.
> Unsubscribes a handler from listening to an event
- `event` is the name of the event to be published. Optionally, `unsubscribe` accepts an object of form `{ event, handler}` coming from `subscribe`.
> Removes all currently active event listeners and unsets the event times.
_Note: this endpoint is not available on the global pub-sub because it could have undesired side effects. You need to unsubscribe global event listeners manually instead._
The global pub-sub instance is created when `pub-sub-es.js` is loaded and provides a way for
global messaging within and between contexts. It utilizes the [Broadcast Channel API](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel), which is [currently not available in all browsers](https://caniuse.com/#feat=broadcastchannel). If you need to support more browsers you have to load a [polyfill](https://gist.github.com/alexis89x/041a8e20a9193f3c47fb). PubSubES is _not_ taking care of that! Also, when sending sending objects from one context to another you have to make sure that they are clonable. For example, trying to broadcast a reference to a DOM element will fail.
You might have come across the awesome [PubSubJS](https://github.com/mroderick/PubSubJS) library and wonder which one to choose. First of all, both are tiny, have no dependencies, and offer async event broadcasting. The two main features that PubSubES offers are:
1. Auto-unsubscribable event listening: via `pubSub.subscribe(eventName, eventHandler, t)` you can make the `eventHandler` unsubscribed from `eventName` automatically after `eventName` was broadcasted `t` times.
2. Between-context messaging: PubSubES supports the new Broadcast Channel API so you can send events between different browser contexts, e.g., tabs.
[![npm version](https: