2.1.1 • Published 5 years ago

@thenja/event-emitter v2.1.1

Weekly downloads
4
License
MIT
Repository
github
Last release
5 years ago

Test Coverage-shield-badge-1

EventEmitter

Simple service used to emit and subscribe to events.

How to use

npm install @thenja/event-emitter --save

Installation

Typescript

import { EventEmitter } from '@thenja/event-emitter';
let eventEmitter = new EventEmitter();

Javascript (browser)

<script src="dist/event-emitter.min.js" type="text/javascript"></script>
var eventEmitter = new EventEmitter();

Methods

MethodDescription
emit(eventName: string, data: any)Emit the event to any subscribers
subscribe(eventName: string, fn: Function, options?: iSubscribeOptions)Subscribe to an event, the function will be called once the event is emitted
unsubscribe(eventName: string, fn: Function)Unsubscribe from an event

Use cases & examples

Use as a service

This will be handy if you need a publish and subscribe service for an entire application, you will probably create the EventEmitter class as a singleton for this.

import { EventEmitter } from '@thenja/event-emitter';

let eventEmitter = new EventEmitter();
let fnOne = (data) => {
  console.log('custom-event fired with value: ' + data.val);
};
eventEmitter.subscribe('custom-event', fnOne);
eventEmitter.emit('custom-event', { val: 10 });
eventEmitter.unsubscribe('custom-event', fnOne);

Extending EventEmitter

import { EventEmitter } from '@thenja/event-emitter';

class AppEvents extends EventEmitter {}
const appEvents = new AppEvents();

class Home {
  listen() {
    // you can set the scope to this object
    appEvents.subscribe('event-1', this.listener, { scope: this });
  }

  private listener(data) {
    const val = this.sayHi();
    expect(val).toEqual('Hi');
  }

  private sayHi() { return 'Hi'; }
}
const home = new Home();
home.listen();
appEvents.emit('event-1', { val: 10 });

Use abstract class

A class that extends the EventEmitterAbstract class will basically have a property (this.event) exposed which is just an instance of the EventEmitter class. Useful if you want to emit and listen to events inside of a class.

import { EventEmitterAbstract } from '@thenja/event-emitter';

class MyClass extends EventEmitterAbstract {
  public val: number = 0;

  constructor() {
    super();
    this.event.subscribe('custom-event', this.listenForCustomEvent);
  }

  private listenForCustomEvent() {
    this.val = 10;
  }

  doSomething() {
    this.event.emit('custom-event', {});
  }
}

let myClass = new MyClass();
myClass.doSomething();
// Now myClass.val should equal 10

Emittable events abstract class

This is useful if you have a service (normally a singleton) that is used throughout your application and you want to be able to emit events from the service.

Basic usage:

import { EmittableEvents } from '@thenja/event-emitter';

class UserService extends EmittableEvents {
  addUser(username: string) {
    // perform some functionality to add a user
    // ...
    // now emit an event
    this.emit('user-added', { username: username });
  }
}

// normally a service is a singleton used throughout an application
let userSrv = new UserService();
let userAdded = (data) => {
  // event is fired when a user is added
};
userSrv.on('user-added', userAdded);
userSrv.addUser('nathan');
userSrv.off('user-added', userAdded);

Setting the "this" scope

// this will be our singleton service class
class ScopeTest extends EmittableEvents {
  public fireEvent() {
    this.emit('test-event', { val: 100 });
  }
}

class ListenTest {
  private scopeTest: ScopeTest;
  val: any = null;

  constructor(scopeTest: ScopeTest) {
    this.scopeTest = scopeTest;
    // when you listen to the event, set the scope to "this" so that the 
    // this keyword refers to the listenTest instance
    this.scopeTest.on('test-event', this.listenToEvent, { scope: this });
  }

  listenToEvent(data) {
    this.val = data.val;
  }
}

let scopeTest = new ScopeTest();
let listenTest = new ListenTest(scopeTest);
scopeTest.fireEvent();
expect(listenTest.val).toEqual(100);

Only one listener per event

Sometimes you may only want to have one listener function per event, we can accomplish this by using a unqiue id

let fired = 0;
let myClass = new MyClass();
let listener = (data) => {
  fired++;
};
let listenerTwo = (data) => {
  fired++;
};
// even know we attach two listeners, only the last listener will be used 
// because we have set a uniqueId
myClass.on('testing', listener, { uniqueId: "myUniqueId" });
myClass.on('testing', listenerTwo, { uniqueId: "myUniqueId" });
myClass.fireEvent('testing');
expect(fired).toEqual(1);

Development

npm run init - Setup the app for development (run once after cloning)

npm run dev - Run this command when you want to work on this app. It will compile typescript, run tests and watch for file changes.

Distribution

npm run build -- -v <version> - Create a distribution build of the app.

-v (version) - Optional Either "patch", "minor" or "major". Increase the version number in the package.json file.

The build command creates a /compiled directory which has all the javascript compiled code and typescript definitions. As well, a /dist directory is created that contains a minified javascript file.

Testing

Tests are automatically ran when you do a build.

npm run test - Run the tests. The tests will be ran in a nodejs environment. You can run the tests in a browser environment by opening the file /spec/in-browser/SpecRunner.html.

License

MIT © Nathan Anderson