Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@silvermine/event-emitter

Package Overview
Dependencies
Maintainers
3
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@silvermine/event-emitter - npm Package Compare versions

Comparing version 1.0.1 to 2.0.0

src/lib/is-array-of-strings.js

2

.nycrc.json
{
"include": [
"lib/**/*.js"
"src/**/*.js"
],

@@ -5,0 +5,0 @@ "extension": [

{
"name": "@silvermine/event-emitter",
"version": "1.0.1",
"version": "2.0.0",
"description": "a simple event emitter mixin that is well-tested, solid, and dependency-free",
"main": "src/index.js",
"scripts": {
"commitlint": "commitlint --from 9f45934",
"commitlint": "commitlint --from c798aab",
"test": "check-node-version --npm 6.14.12 --print && nyc mocha -- 'tests/**/*.test.js'"

@@ -30,2 +30,3 @@ },

"homepage": "https://github.com/silvermine/event-emitter#readme",
"types": "src/types/index.d.ts",
"devDependencies": {

@@ -32,0 +33,0 @@ "@silvermine/eslint-config": "3.0.1",

@@ -21,7 +21,7 @@ # Silvermine Event Emitter

browser. For server-side usage, simply use the built-in `require` function to `require
('silvermine-event-emitter')` and use the mixin. For browser environments, use a CommonJS
('@silvermine/event-emitter')` and use the mixin. For browser environments, use a CommonJS
module loader like [Browserify](http://browserify.org/) or
[Webpack](https://webpack.github.io/).
`silvermine-event-emitter` uses native [Promises][] to make event listener executions
`@silvermine/event-emitter` uses native [Promises][] to make event listener executions
asynchronous. Native Promises are available in node.js versions `0.12.18` and up, and in

@@ -32,3 +32,3 @@ [most browsers](http://caniuse.com/#feat=promises) except Internet Explorer. If you need

`silvermine-event-emitter` also uses these built-in `Array` methods that are only
`@silvermine/event-emitter` also uses these built-in `Array` methods that are only
available in Internet Explorer 9 and up:

@@ -44,3 +44,3 @@

The object returned by `require('silvermine-event-emitter')` is designed to be used as a
The object returned by `require('@silvermine/event-emitter')` is designed to be used as a
mixin for javascript "classes". Here are a few different ways in which the mixin can be

@@ -50,4 +50,4 @@ used:

```js
var EventEmitterMixin = require('silvermine-event-emitter'),
MyClass, myInstance;
const { EventEmitterMixin } = require('@silvermine/event-emitter').EventEmitterMixin,
MyClass, myInstance;

@@ -68,3 +68,3 @@ MyClass = function() {};

```js
var EventEmitterMixin = require('silvermine-event-emitter'),
var EventEmitterMixin = require('@silvermine/event-emitter').EventEmitterMixin,
myInstance;

@@ -84,5 +84,4 @@

```js
const { EventEmitterMixin } = require('@silvermine/event-emitter');
let EventEmitterMixin = require('silvermine-event-emitter');
let MixinEventEmitter = (Base) => {

@@ -101,3 +100,2 @@ Object.assign(Base.prototype, EventEmitterMixin);

myInstance.emit('started');
```

@@ -210,4 +208,3 @@

You may want to bind one event listener to several event names. You can either bind them
individually or within a single call to `on` by passing a space-delimited list of event
names:
individually or within a single call to `on` by passing an array of event names:

@@ -217,3 +214,3 @@ ```js

myInstance.on('started stopped paused', onChange);
myInstance.on([ 'started', 'stopped', 'paused' ], onChange);

@@ -228,7 +225,7 @@ // or:

You can emit multiple events with a single call to `emit` by passing a space-delimited
list of event names:
You can emit multiple events with a single call to `emit` by passing an array of event
names:
```js
myInstance.emit('initialized started played');
myInstance.emit([ 'initialized', 'started', 'played' ]);
```

@@ -315,2 +312,29 @@

##### A warning about arrow functions
JavaScript does not allow you to re-bind the `this` context of an arrow function. If you
pass an arrow function as a listener, the `context` parameter will have no effect. For
example:
```js
const outerContext = this;
function registerListeners() {
// The `outerContext` parameter will be ignored. The listener will have the `this`
// context that `registerListeners` is called with.
myInstance.on('started', () => { console.log('Started', this.name); }, outerContext);
}
```
If you need to re-bind the context, use a `function` statement instead:
```js
const outerContext = this;
function registerListeners() {
// The listener function will have `outerContext` as its `this` context.
myInstance.on('started', function() { console.log('Started', this.name); }, outerContext);
}
```
## How do I contribute?

@@ -317,0 +341,0 @@

@@ -5,65 +5,7 @@ 'use strict';

reject = require('./lib/reject'),
isArrayOfStrings = require('./lib/is-array-of-strings'),
EventEmitterMixin;
/**
* Can be used as a mixin when making a class that needs to be an EventEmitter.
*
* e.g. `Object.assign(MyClass.prototype, EventEmitterMixin);`
*
* Note: if it is necessary to override a listener function's `this` context, always use
* the optional `context` parameter on the {@link EventEmitterMixin#on} method to do so
* if you want to remove that specific listener or listener and context combination
* later. If you are using {@link EventEmitterMixin#once} or never need to remove the
* event listener, using `listener.bind(context)` instead of the context parameter is
* acceptable.
*
* It is common to override a listener function's `this` context using the `Function`
* object's `bind` method. For example:
*
* ```
* emitter.on('ready', this.onReady.bind(this));
* ```
*
* However, doing so will make it impossible to remove that listener function without
* calling `emitter.off('ready')`, which would remove **all** listeners for the `ready`
* event.
*
* This happens because calling `.bind(context)` on a function produces a completely
* new `Function` instance. When it's time to remove an event listener that was bound
* to a context using the `bind` function, calling `bind` on the same function will
* produce a different instance that does not pass an equality check with the
* previously bound function. For example:
*
* ```
* var fn = function() {},
* context = {};
*
* fn === fn; // true
* fn.bind(context) === fn.bind(context); // false
* ```
*
* And so:
*
* ```
* emitter.on('ready', fn.bind(context));
* emitter.off('ready', fn.bind(context));
* ```
*
* does not remove the event listener that is listening to `'ready'` which results in a
* memory leak. The correct way is to use the third argument to `on`, which lets you
* specify the context for the `listener` function:
*
* ```
* emitter.on('ready', fn, context);
* ```
*
* Then, to remove that particular listener, call {@link EventEmitterMixin#off} and pass
* the same event name, function, and context:
*
* ```
* emitter.off('ready', fn, context);
* ```
*
* @mixin
*/
// See the full JSDoc documentation for this object and its public methods in
// ./types/index.d.ts
EventEmitterMixin = {

@@ -82,42 +24,7 @@

/**
* Register a listener function that will be called every time the specified event is
* emitted.
*
* Calls to `on` will de-duplicate listeners so that the same listener and context
* combination does not get invoked more than once for the same event. Also, calls
* to `on` override calls to {@link EventEmitterMixin#once} in that if there is still
* an event listener and context combination registered from a call to
* {@link EventEmitterMixin#once} and the same listener and context combination is
* passed to a call to `on`, that listener and context combination will **not** be
* removed after the first event.
*
* If the `listener` function (or the listener function and its associated `context`)
* was already registered using {@link EventEmitterMixin#on} or
* {@link EventEmitterMixin#once}, registering it again with `on` will have the
* following effect:
*
* * `on`: if it was registered with `on`, nothing happens. There remains one
* listener registered for the `eventNames` event(s).
* * `once`: if it was registered with `once`, and the `eventName` event has not
* been emitted yet, then that listener becomes an `on` listener, is executed each
* time that the event is emitted, and is **not** removed after it has been called
* once.
*
* @param eventNames {string} one or more names of the event(s) your listener will be
* invoked for, when emitted. Providing a string of space-separated names will bind
* the provided listener to each of the events listed.
* @param listener {function} the listener that will be called when this event is
* emitted
* @param [context] {object} the object that will be the `this` context for the
* `listener` function when it is executed. See the documentation on
* {@link EventEmitterMixin} for an explanation of when and how to use this parameter.
* @instance
* @returns {object} `this` for chaining
*/
on: function(eventNames, listener, context) {
var eventNamesList;
if (typeof eventNames !== 'string') {
throw new Error('the eventNames parameter must be a string, but was: ' + (typeof eventNames));
if (typeof eventNames !== 'string' && !isArrayOfStrings(eventNames)) {
throw new Error('the eventNames parameter must be a string or an array of strings, but was: ' + eventNames);
}

@@ -127,3 +34,3 @@ if (typeof listener !== 'function') {

}
eventNamesList = eventNames.split(' ');
eventNamesList = Array.isArray(eventNames) ? eventNames : [ eventNames ];

@@ -197,60 +104,2 @@ // Remove the event listeners if they already exist. Listeners bound with this `on`

/**
* Register a listener function that will be called only once. After the listener is
* invoked for the first time, it will be discarded.
*
* If the `listener` function or the `listener` function and context is already
* registered using either {@link EventEmitterMixin#on} or
* {@link EventEmitterMixin#once}, this operation essentially has no effect.
*
* Unlike the {@link EventEmitterMixin#on} function, this function can only register
* a listener for one `eventName` at a time. This saves us from a large amount of
* complexity in the EventEmitter API. For example:
*
* ```
* var listener = function() {};
*
* eventEmitter
* .once('a b c', listener)
* .on('b', listener)
* .emit('b');
* ```
*
* Should there be one event listener bound for each of 'a', 'b', and 'c'? Or would
* `listener` only execute one time for 'a' *or* 'b' *or* 'c'? Further, if the 'b'
* event is emitted, as shown above, would you expect `listener` to be executed once,
* or twice? If 'c' is then emitted after 'b', should `listener` be executed again, or
* was it removed as the result of emitting 'b'? Even a simple example raises many
* questions with non-obvious answers. Allowing `once` to register only one event
* listener at a time gives us a more straightforward API that is easy to understand
* and reason about.
*
* If you would like to create a listener that will only execute once across multiple
* event names, you can do so using the Underscore or Lodash library's `_.once`
* function. For example:
*
* ```
* var listener = _.once(function() {});
*
* eventEmitter
* .once('a', listener)
* .once('b', listener)
* .once('c', listener);
* ```
*
* Then, when either the 'a', 'b', or 'c' events are emitted, the listener function
* will be invoked once and will not be invoked again for any 'a', 'b', or 'c' events.
* However, note that if the other two events are not emitted then `listener` remains
* in memory. In the example above, if 'a' is emitted then the `listener` function
* remains registered and in-memory for events 'b' and 'c' until both 'b' and 'c'
* are emitted.
*
* @param eventName {string} the name of the event your listener will be invoked on.
* @param listener {function} the listener that will be called the first time this
* event is emitted
* @param [context] {object} the object that will be the `this` context for the
* `listener` function when it is executed
* @instance
* @returns {object} `this` for chaining
*/
once: function(eventName, listener, context) {

@@ -263,6 +112,2 @@ var self = this,

}
if (eventName.indexOf(' ') !== -1) {
throw new Error('The eventName parameter cannot contain the name of more than one event and so it '
+ 'should not contain a space. The eventName parameter was: ' + eventName);
}
if (typeof listener !== 'function') {

@@ -293,35 +138,5 @@ throw new Error('the listener parameter must be a function, but was: ' + (typeof listener));

/**
* Removes event listeners.
*
* If this function is called with no parameters, then all event listeners bound to
* this object will be removed.
*
* If only the `eventNames` parameter is provided, then all listeners bound to each
* name in `eventNames` will be removed.
*
* If the `eventNames` and `listener` parameters only are provided, then all listeners
* for each name in `eventNames` that use the given `listener` function will be
* removed.
*
* If all three `eventNames`, `listener`, and `context` parameters are provided, for
* each event name in `eventNames`, only the listener registered with that specific
* event name, `listener` function, and context will be removed.
*
* @param [eventNames] {string} the name(s) of one or more events. Providing a string
* of space-separated names will remove the listeners for each of the events listed.
* Omitting this parameter will remove all event listeners from this object.
* @param [listener] {function} the listener that will be removed. If this parameter
* is not provided, then **all** event listeners listening to each `eventName` will be
* removed.
* @param [context] {object} the object that was provided as the `this` context for
* the `listener` function when the event listener you are removing was registered.
* See the documentation on {@link EventEmitterMixin} for an explanation of when and
* how to use this parameter. If this parameter is not provided, then **all** event
* listeners listening to each `eventName` using the given `listener` function will be
* removed.
* @instance
* @returns {object} `this` for chaining
*/
off: function(eventNames, listener, context) {
var eventNamesList;
if (!eventNames) {

@@ -331,3 +146,5 @@ this._eventListeners = {};

}
eventNames.split(' ').forEach(function(eventName) {
eventNamesList = Array.isArray(eventNames) ? eventNames : [ eventNames ];
eventNamesList.forEach(function(eventName) {
this._removeEventListener(eventName, listener, context);

@@ -375,21 +192,14 @@ }.bind(this));

/**
* Emits an event to any listeners registered for it.
*
* @param eventNames {string} the names of one or more events to emit. Providing a
* string of space-separated names will emit each of the events listed.
* @param * {...*} all other arguments will be passed to the event listeners
* @instance
* @returns {object} `this` for chaining
*/
emit: function(eventNames) {
var args = Array.prototype.slice.apply(arguments),
eventArgs = args.slice(1);
eventArgs = args.slice(1),
eventNamesList;
if (typeof eventNames !== 'string') {
throw new Error('the eventNames parameter must be a string, but was: ' + (typeof eventNames));
if (typeof eventNames !== 'string' && !isArrayOfStrings(eventNames)) {
throw new Error('the eventNames parameter must be a string or an array of strings, but was: ' + eventNames);
}
eventNames.split(' ').forEach(function(eventName) {
eventNamesList = Array.isArray(eventNames) ? eventNames : [ eventNames ];
eventNamesList.forEach(function(eventName) {
this._emitEvent(eventName, eventArgs);

@@ -431,2 +241,20 @@ }.bind(this));

module.exports = EventEmitterMixin;
// Export the EventEmitterMixin as an ES-Module-compatible named export.
//
// TypeScript and ES-Module users will import the EventEmitterMixin object using the
// `import { EventEmitterMixin } from '@silvermine/event-emitter'` syntax and CommonJS
// users can use the object destructuring syntax: `const { EventEmitterMixin } =
// require('@silvermine/event-emitter')`
//
// Why not just use `module.exports = EventEmitterMixin` here as we did in v1.x? To add
// proper TypeScript types for `module.exports = SOMETHING`, you have to use the `export =
// SOMETHING` statement in your .d.ts file. TypeScript provides the `export =` statement
// for exactly this use case. However, using it means you cannot export any other object,
// type, or interface in that file. This means that we'd only be able to export the
// `EventEmitterMixin` object itself, and not the `IEventEmitter` interface. That would be
// very inconvenient for TypeScript users.
//
// Instead, we export the `EventEmitterMixin` as a named export. This allows us to export
// both the `IEventEmitter` interface and the `EventEmitterMixin` object in
// `./types/index.d.ts`.
module.exports.EventEmitterMixin = EventEmitterMixin;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc