UNPKG

ee-proxy

Version:

Event emitter proxy for easy local listeners cleanup

216 lines (160 loc) 6.72 kB
# ee-proxy Event emitter proxy for easy local listeners cleanup [![NPM version](https://img.shields.io/npm/v/ee-proxy.svg)](https://npmjs.org/package/ee-proxy) [![Build status](https://img.shields.io/travis/Jokero/ee-proxy.svg)](https://travis-ci.org/Jokero/ee-proxy) **Note:** This module works in browsers and Node.js >= 6.0. Use `Proxy` and `Array` polyfills for Internet Explorer ## Table of Contents - [Demo](#demo) - [Installation](#installation) - [Node.js](#nodejs) - [Browser](#browser) - [Overview](#overview) - [Usage](#usage) - [emitterProxy(object, [options])](#emitterProxy-object-options) - [Parameters](#parameters) - [Return value](#return-value) - [Example](#example) - [Polyfill](#polyfill) - [Build](#build) - [Tests](#tests) - [License](#license) ## Demo Try [demo](https://runkit.com/npm/ee-proxy) on RunKit. ## Installation ```sh npm install ee-proxy ``` ### Node.js ```js const emitterProxy = require('ee-proxy'); ``` ### Browser ``` <script src="node_modules/ee-proxy/dist/ee-proxy.js"> ``` or minified version ``` <script src="node_modules/ee-proxy/dist/ee-proxy.min.js"> ``` You can use the module with AMD/CommonJS or just use `window.emitterProxy`. ## Overview `ee-proxy` allows you to easily and safely remove listeners attached to event emitter without touching listeners added in other pieces of code. Unlike other similar modules (for example, [ultron](https://www.npmjs.com/package/ultron)) this one works seamlessly and allows to call your custom methods on event emitter: ```js const emitterProxy = require('ee-proxy'); const EventEmitter = require('events'); class Game extends EventEmitter { start() { console.log('Game started'); } } const game = emitterProxy(new Game()); game.start(); // Game started console.log(game instanceof EventEmitter); // true console.log(game instanceof Game); // true ``` ## Usage ### emitterProxy(emitter, [options]) #### Parameters - `emitter` (EventEmitter) - `[options]` (Object) - `[stopListeningAfterFirstEvent]` (boolean) - If `true`, `ee-proxy` removes all listeners attached to the wrapped emitter when first event is triggered (might be useful in some cases) - `[removeMethod]` (string) - Name of the method for listeners cleanup (default - `stopListening`) - `[addListenerMethods]` (string[]) - Methods which are intercepted by `ee-proxy` for keeping attached to emitter listeners (default - `['on', 'once', 'addListener', 'prependListener', 'prependOnceListener', 'onceAny', 'onAny']`) - `[fields]` (string[]) - Option specially for `Proxy` polyfill (see [below](#polyfill)) #### Return value (EventEmitter) - Proxy object (which is `!==` original emitter) ```js const user = new EventEmitter(); user.once('disconnect', () => console.log('User disconnected')); const wrappedUser = emitterProxy(user); wrappedUser.once('game:start', () => console.log('User is ready to start the game')); wrappedUser.once('game:cancel', () => console.log('User cancelled the game')); wrappedUser.once('disconnect', () => console.log('User disconnected')); wrappedUser.stopListening(); // removes all attached to the wrapped emitter listeners console.log(user.listenerCount('disconnect')); // 1 // wrappedUser.stopListening('game:start'); // you can specify a particular event // wrappedUser.stopListening('game:start', 'game:cancel'); // or even list several events ``` ### Examples #### Basic example ```js const EventEmitter = require('events'); const emitterProxy = require('ee-proxy'); const user = new EventEmitter(); user.once('disconnect', () => console.log('User disconnected')); class Game extends EventEmitter { constructor(user) { super(); this._user = emitterProxy(user); this._user.once('game:cancel', () => this._onUserLeft()); this._user.once('disconnect', () => this._onUserLeft()); } start() { this._user.on('game:message', message => console.log('game:message', message)); this._user.on('game:command', command => console.log('game:command', command)); } _onUserLeft() { console.log('User left the game'); this._user.stopListening(); // removes only game listeners ("game:message" and "game:command" events) this.emit('canceled'); } } const game = new Game(user); game.start(); console.log(user.listenerCount('disconnect')); // 2 console.log(user.listenerCount('game:cancel')); // 1 console.log(user.listenerCount('game:message')); // 1 console.log(user.listenerCount('game:command')); // 1 game.once('canceled', () => { console.log(user.listenerCount('disconnect')); // 1 console.log(user.listenerCount('game:cancel')); // 0 console.log(user.listenerCount('game:message')); // 0 console.log(user.listenerCount('game:command')); // 0 }); user.emit('game:cancel'); ``` #### Using of "stopListeningAfterFirstEvent" option Sometimes you may need to listen to several events and you want to react only on first one. For example, your user can have a choice: to start the game, to cancel it or the user can even disconnect. In that case you can call `stopListening()` in every event listener but it's much easier just to set `stopListeningAfterFirstEvent=true`: ```js const user = new EventEmitter(); user.once('disconnect', () => console.log('User disconnected')); const wrappedUser = emitterProxy(user, { stopListeningAfterFirstEvent: true }); wrappedUser.once('game:start', () => console.log('User is ready to start the game')); wrappedUser.once('game:cancel', () => console.log('User cancelled the game')); wrappedUser.once('disconnect', () => console.log('User disconnected')); user.emit('game:cancel'); console.log(user.listenerCount('disconnect')); // 1 console.log(user.listenerCount('game:start')); // 0 console.log(user.listenerCount('game:cancel')); // 0 ``` ### Polyfill Internet Explorer and some other outdated browsers don't support `Proxy` (see [caniuse](https://caniuse.com/#search=proxy)). In this case you can use [polyfill](https://github.com/GoogleChrome/proxy-polyfill). But keep in mind that all emitter properties you will use **must be known at proxy creation time** because polyfill seals an emitter object, preventing new properties from being added to it. But you can workaround it by using `fields` option: ```js const emitterProxy = require('ee-proxy'); const EventEmitter = require('events'); class Game extends EventEmitter { start() { console.log('Game started'); } } const game = emitterProxy(new Game(), { fields: 'something' }); game.something = '123456'; ``` ## Build ```sh npm install npm run build ``` ## Tests ```sh npm install npm test ``` ## License [MIT](LICENSE)