npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

events-ex

v2.0.0

Published

Browser-friendly enhanced events most compatible with standard node.js, it's powerful eventable ability.

Downloads

967

Readme

events-ex Build Status npm downloads license

Browser-friendly enhanced event emitter ability and class. It's modified from event-emitter mainly. It can add/inject the event-able ability to your any class.

Features

  • Rewrite of the core architecture for improved performance and more powerful event-able ability
  • keep most compatible with node events and event-emitter
  • Supports bubbling and interruption
    • Hook-able event system for more control over event handling
  • Supports async event emitting via emitAsync method which will wait for all async listeners to complete before returning.
  • Subscribe events with regular expression

Differences

  • Difference with node events
    • broken change: The event supports bubbling and interruption
      • the event object as listener's "this" object:
        • result: If set, the result is returned to the Event Emitter.
        • stopped: If set to true, it prevents the remaining listeners from being executed.
        • target: The Event Emitter object, which was originally the this object.
        • type: triggered event type(name).
      • broken change: The emit return the result of listeners's callback function instead of the successful state.
      • broken change: The this object of listeners' callback function is the Event Object instead of the emitter object.
        • The emitter object is put into the target property of the Event Object.
    • Adds async event emitting via emitAsync method.
  • Difference with event-emitter
    • broken change: The event supports bubbling and interruption(see above)
    • Adds the defaultMaxListeners class property to keep compatibility with node events.
    • Adds the setMaxListeners method to keep compatible with node events.
    • Adds error, newListener and removeListener events to keep compatibility with node events.
    • Adds listeners() method to keep compatibility with node events.
    • Adds listenerCount() class method to keep compatibility with node events.
    • Adds async event emitting via emitAsync method.

Note: The listener throw error should not broke the notification, but it will emit error(emit('error', error, 'notify', eventName, listener, args)) after notification.

Installation

npm install events-ex

Usage

Extends from EventEmitter class:

import {EventEmitter} from 'events-ex';

class MyClass extends EventEmitter {}

Add/Inject the event-able ability to your class directly:

import {eventable} from 'events-ex';

class MyClass extends MyRoot {}

// inject the eventable ability to MyClass
eventable(MyClass);

Now, you can use events in your class:

const my = new MyClass;

my.on('event', function() {
  console.log('event occur');
});

my.on(/^event/, function() {
  console.log('regexp match multi events');
});


my.emit('event');
my.emit('event1');

Bubbling event usage:

import {EventEmitter, states} from 'events-ex';
import {isObject} from 'util-ex';

states.ABORT = -1
class MyDb extends EventEmitter {
  get(key) {
    // Demo the event object bubbling usage:
    let result = this.emit('getting', key)
    if(isObject(result)) {
      if (result.state === states.ABORT) return
      if (result.state === states.DONE)  return result.result
    }
    return _get(key)
  }
}

let db = new MyDb
db.on('getting', function(key){
  result = myGet(key);
  if (result != null) {
    // get the key succ
    this.result = {
      state: states.DONE,
      result: result,
    }
    this.stopped = true // it will skip other listeners if true
  } else {
    // you can abort to get key by default.
    this.result = {state: states.ABORT};
    // this.stopped = true // it will skip other listeners if true
  }
})

event-emitter usage:


import {wrapEventEmitter as ee} from 'events-ex';

class MyClass { /* .. */ };
ee(MyClass.prototype); // All instances of MyClass will expose event-emitter interface

const emitter = new MyClass();
let listener;

emitter.on('test', listener = function (args) {
  // … react to 'test' event
});

emitter.once('test', function (args) {
  // … react to first 'test' event (invoked only once!)
});

emitter.emit('test', arg1, arg2/*…args*/); // Two above listeners invoked
emitter.emit('test', arg1, arg2/*…args*/); // Only first listener invoked

emitter.off('test', listener);              // Removed first listener
emitter.emit('test', arg1, arg2/*…args*/); // No listeners invoked

API

eventable(class[, options]) (events-ex/eventable)

Add the event-able ability to the class directly.

  • class: the class to be injected the ability.
  • options (object): optional options
    • include (string[]|string): only these emitter methods will be added to the class
      • NOTE: static method should use the prefix '@' with name.
    • exclude (string[]|string): theses emitter methods would not be added to the class
      • NOTE: static method should use the prefix '@' with name.
    • methods (object): hooked methods to the class
      • key: the method name to hook.
      • value: the new method function
        • use this.super() to call the original method.
        • this.self is the original this object.
    • classMethods (object): hooked class methods to the class
  import {eventable} from 'events-ex'

  class OtherClass {
    exec() {console.log "my original exec"}
  }

  class MyClass {}
    // only 'on', 'off', 'emit', 'emitAsync' and static methods 'listenerCount' added to the class
  eventable(MyClass, include: ['on', 'off', 'emit', 'emitAsync', '@listenerCount'])

  // add the eventable ability to OtherClass and inject the exec method of OtherClass.
  eventable(OtherClass, {methods: {
    exec() {
      console.log("new exec")
      this.super() //call the original method
    }}
  })

allOff(obj) (events-ex/all-off)

keep compatible only: the removeAllListeners has already been buildin.

Removes all listeners from given event emitter object

hasListeners(obj[, name]) (events-ex/has-listeners)

Whether object has some listeners attached to the object. When name is provided, it checks listeners for specific event name

import {hasListeners, wrapEventEmitter as ee} from 'events-ex/has-listeners';
var emitter = ee();
var listener = function () {};

hasListeners(emitter); // false

emitter.on('foo', listener);
hasListeners(emitter); // true
hasListeners(emitter, 'foo'); // true
hasListeners(emitter, 'bar'); // false

emitter.off('foo', listener);
hasListeners(emitter, 'foo'); // false

pipe(source, target[, emitMethodName]) (events-ex/pipe)

Pipes all events from source emitter onto target emitter (all events from source emitter will be emitted also on target emitter, but not other way). Returns pipe object which exposes pipe.close function. Invoke it to close configured pipe. It works internally by redefinition of emit method, if in your interface this method is referenced differently, provide its name (or symbol) with third argument.

unify(emitter1, emitter2) (events-ex/unify)

Unifies event handling for two objects. Events emitted on emitter1 would be also emitter on emitter2, and other way back. Non reversible.

import {unify as eeUnify, wrapEventEmitter as ee} from 'events-ex';

var emitter1 = ee(), listener1, listener3;
var emitter2 = ee(), listener2, listener4;

emitter1.on('test', listener1 = function () { });
emitter2.on('test', listener2 = function () { });

emitter1.emit('test'); // Invoked listener1
emitter2.emit('test'); // Invoked listener2

var unify = eeUnify(emitter1, emitter2);

emitter1.emit('test'); // Invoked listener1 and listener2
emitter2.emit('test'); // Invoked listener1 and listener2

emitter1.on('test', listener3 = function () { });
emitter2.on('test', listener4 = function () { });

emitter1.emit('test'); // Invoked listener1, listener2, listener3 and listener4
emitter2.emit('test'); // Invoked listener1, listener2, listener3 and listener4