event-station
Version:
A versatile and robust event emitter class.
393 lines (263 loc) • 11 kB
Markdown
# Usage
This guide will explain the general usage of Event-Station.
More examples can be found in the [Examples document](./Examples.md), or in the [tests](../tests).
## Table of Contents
- [Terminology](#terminology)
- [Configuration](#configuration)
- [Options](#options)
- [Reset](#reset)
- [Listeners](#listeners)
1. [Single Event String](#single-event-name)
2. [Delimited Event Strings](#delimited-event-names)
3. [Event String Array](#event-name-array)
4. [Listener Map](#listener-map)
- [Attaching Listeners](#attaching-listeners)
- [Removing Listeners](#removing-listeners)
- [Asynchronous Listeners](#asynchronous-listeners)
- [Emitting Events](#emitting-events)
- [Providing Context](#providing-context)
- [Cross-emitter Listening](#cross-emitter-listening)
- [Limiting Occurrences](#limiting-occurrences)
- [Regular Expression Listeners](#regular-expression-listeners)
- [Listener Modifiers](#listener-modifiers)
- [Browser Usage](#browser-usage)
- [Inheritance](#object-inheritance)
- [ES6](#es6)
- [ES5](#es5)
- [CoffeeScript](#coffeescript)
- [Object Literal](#object-literal)
## Terminology
- `student` and `teacher` are used as examples of `EventStation` instances.
## Configuration
Event-Station can be configured globally using the `config()` static method.
```javascript
EventStation.config(options);
```
`EventStation` instances can configured during initialization by giving the constructor an object of options.
```javascript
new EventStation(options);
```
### Options
#### emitAllEvent
Determines whether an emitter emits an `"all"` event for every event that is emitted.
| Type | Default |
| --------- | ------- |
| `boolean` | `true` |
#### enableRegExp
Determines whether an emitter can use regular expression listeners.
| Type | Default |
| --------- | ------- |
| `boolean` | `false` |
#### regExpMarker
The character used to mark regular expression listeners.
| Type | Default |
| -------- | ------- |
| `string` | `"%"` |
#### enableDelimiter
Determines whether an emitter can use delimited event names.
| Type | Default |
| --------- | ------- |
| `boolean` | `true` |
#### delimiter
The character used to delimit event names in a string.
| Type | Default |
| -------- | ------------- |
| `string` | `" "` (space) |
### Reset
Global configuration can be reset without affecting existing stations by invoking `EventStation.reset();`
_**Note:** Invoking the global reset also resets injected dependencies._
## Listeners
Each listener is an object with its own state. As a result, listeners can maintain their state while being paused or detached from emitters.
Listener methods on the `EventStation` class share the same basic interface, which accepts:
- A `string` with a single event
```javascript
"foo";
```
- A `string` of delimited events
```javascript
"foo bar";
```
- An `Array` of `string` events
```javascript
["foo", "bar"];
```
- A listener map with events as keys and callbacks as properties
```javascript
{
foo: function () {},
bar: function () {},
}
```
### Single Event
A single event can be given to create one listener for one event.
```javascript
let listeners = student.on("wakeup", function () {
console.error("No, five more minutes, please.");
});
```
### Delimited Event
Delimited events can be given to create multiple listeners with the same callback and/or context.
By default, events are delimited by spaces. This can be changed by setting the [`delimiter`](#delimiter) option.
```javascript
let listeners = student.on("eating-breakfast taking-shower", function () {
console.warn("I'm running late!");
});
```
### Event Array
An array of events can be given to create multiple listeners with the same callback and/or context.
Delimiters are ignored in event arrays.
```javascript
let listeners = student.on(["need more", "sleep"], function () {
console.warn("I'm really late!");
});
```
### Listener Map
A listener map can be given to create multiple listeners, each with a different callback.
Optionally, a shared context can also be given.
_**Note:** Delimiters are ignored in listener maps._
```javascript
let listeners = student.on({
forgotHomework: function () {
console.error("I'm in trouble.");
},
"forgot-books": function () {
console.error("This is bad.");
},
});
```
## Attaching Listeners
Listeners can be added via the `on()`, `once()`, `hear()`, and `hearOnce()` methods.
The `addTo()` and `moveTo()` listener modifiers can also be used to add listeners to an emitter.
```javascript
student.on("read", function () {
console.log("The student is reading.");
});
let listeners = student.hear(teacher, "lecture", function () {
console.log("Someone is lecturing.");
});
// The same listener is now listening for 'lecture' events by both the student and teacher.
listeners.addTo(student);
```
## Removing Listeners
Listeners can be removed via the `off()` and `disregard()` methods.
The `removeFrom()` and `moveTo()` listener modifiers can also be used to remove listeners from an emitter.
The `off()` listener modifier will remove the collection of listeners from _all_ emitters.
```javascript
// Removes all listeners from the teacher
// that were attached by the student
student.disregard(teacher);
// Remove all listeners from the emitter
student.off();
// Removes only the listeners that match the callback and context
student.off("study", studyCallback, studyContext);
```
```javascript
let listeners = student.on("read", function () {
console.log("The student is reading.");
});
// Removes the listener from all emitters, including the `student`
listeners.off();
```
## Asynchronous Listeners
An asynchronous listener has a callback that returns a `Promise` compatible object.
Examples of asynchronous listeners:
```javascript
emitter.on("foo", function () {
return new Promise(function (resolve) {
setTimeout(function () {
resolve();
}, 2000);
});
});
emitter.on("bar", function () {
return Promise.reject();
});
```
The `emit()` method doesn't recognize asynchronous listeners, and will simply iterate over them as per normal.
The `emitAsync()` method will capture the returned promises, and return a new promise that will resolve,
when all of the captured promises have resolved.
```javascript
await emitter.emitAsync(["foo", "bar"]);
console.log('All "foo" and "bar" listeners have completed.');
```
_See the [Asynchronous Listeners](./Examples.md#asynchronous-listeners) example._
To clarify, both synchronous and asynchronous listeners can be attached to an emitter, listening to the same event,
and invoked with either `emit()` or `emitAsync()`. However, only `emitAsync()` will handle promises.
In short, `emitAsync()` should be used whenever you want to make sure, that all invoked listeners have finished handling an event.
## Emitting Events
Events are emitted via an emitter's `emit()` or `emitAsync()` methods.
The first argument can be an event string, a string of delimited events, or an array of events.
All arguments after the first are passed to each listener's callback function.
```javascript
teacher.on("lecture", function (bookTitle, pageNumber) {
// We're reading page 741 in History 101.
console.log(`We're reading page ${pageNumber} in ${bookTitle}.`);
});
teacher.emit("lecture", "History 101", 741);
```
## Providing Context
Context can be provided as the last argument on methods that attach listeners.
The `using()` listener modifier can be used to change the context of listeners.
```javascript
let context = new Date();
let listeners = student.on(
"wakeup",
function () {
this.getFullYear();
},
context
);
listeners.using(new Date());
```
## Cross-emitter Listening
Cross-emitter listening is handled via the `hear()`, `hearOnce()`, and `disregard()` methods.
In the following example, the `student` emitter attaches a listener to the `teacher` emitter.
The listener will "remember" that is was attached by the `student` method.
```javascript
student.hear(teacher, "lecture", function (bookTitle, pageNumber) {
student.sleep();
});
```
After the listener is attached, it can be removed via the `disregard()` method.
The following example removes all listeners from the `teacher` that were attached by the `student`.
```javascript
student.disregard(teacher);
```
## Limiting Occurrences
The number of times a listener's callback is invoked can be limited.
Occurrences can be limited via the `occur()` and `once()` listener modifiers, or the `once()` and `hearOnce()` methods.
When a listener reaches its occurrence limit, it will be removed from all emitters which it's attached to.
```javascript
student.once("talk", function () {});
student.on("talk", function () {}).occur(5);
student.hearOnce(teacher, "lecture");
student.hear(teacher, "lecture").once(function () {});
```
## Regular Expression Listeners
Regular expression (RegExp) listeners are disabled by default for improved performance.
RegExp listeners can be enabled globally or per emitter by setting the [`enableRegExp`](#enableRegExp) option.
When enabled, RegExp listeners are recognized by a marker. The marker is a single character located at the beginning of an event.
The RegExp marker is `"%"` by default and can be changed by setting the [`regExpMarker`](#regExpMarker) option.
```javascript
emitter.on("%foo/bar/[^/]+/1", callback);
```
Aside from the marker, the general interface remains unchanged.
In the following code, both a RegExp listener and a normal listener, will be attached to the emitter.
```javascript
emitter.on(["%foo/bar/[^/]+/1", "hello-world"], callback);
```
## Listener Modifiers
Listener modifiers are located on the `EventStation.Listeners` class and provide a fluent interface for modifying Listeners.
A `Listeners` instance can be created via the `on()`, `once()`, `hear()`, `hearOnce()`, `makeListeners()`, and `getListeners()` methods.
Please refer to the [module definition](https://github.com/morrisallison/event-station/blob/main/dist/event-station.d.ts) for details on each modifier.
## Browser Usage
Event-Station can be used in Web browsers that support ES5.
Please view the section on [installation](../README.md#installation) for how to load Event-Station in a Web browser.
If Event-Station is loaded via a `<script>` tag, an `EventStation` global will be assigned.
## Inheritance
The `EventStation` class can be extended directly.
#### ES6
```javascript
class Teacher extends EventStation {}
/* true */ new Teacher() instanceof EventStation;
```