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

emitr

v0.0.8

Published

An node/browser event emitter that supports dispatching based on types.

Downloads

207

Readme

emitr

A simple emitter for node and the browser.

Build Status

The rendered form of this document includes the Emitter script so you can open a console and try it immediately.

My two main inspirations in making this implementation were the events in backbone, and the EventEmitter in node.

If we hadn't required the ability to pass 'context' into on and off, we probably would have gone with LucidJS. Not leaking memory is difficult enough when building large applications; forcing people to keep extra objects around just so they can clean up after themselves is ugly enough that it discourages people from doing something important.

While I haven't come across this exact combination of focussed microlibrary combined with context, the only unusual feature of this Emitter (and deliberately so) is that it allows you to listen to and dispatch objects rather than just strings. Related to this is type based events, which I describe later.

Getting It

In node

$ npm install emitr --save

To get the source (you'll want to npm install it afterwards)

$ git clone https://github.com/BladeRunnerJS/emitr.git

With Bower

$ bower install emitr

In the browser (better to take a copy of the file and serve it from within your app)

<script type="text/javascript" src="http://bladerunnerjs.github.io/emitr/dist/emitr.js"></script>

With require.js (again, better to take a copy and serve it within your app)

require(["http://bladerunnerjs.github.io/emitr/dist/emitr.js"], function(emitr) {
    // do your thing with emitr
});

Making an Emitter

While you can directly create a new Emitter (with new emitr(), or use standard prototypical inheritance to inherit from it, usually you will want to mix the Emitter methods in to your own classes or objects.


	function MyEmitter() {};
	emitr.mixInto(MyEmitter);

	var emitter = new MyEmitter();

Standard Emitter Features

The big three methods are provided:

on:


	// Basic example:

	emitter.on('some-event', function() {
		// By default, 'this' is set to emitter inside here.
		// you can change that by providing a context argument.
	});

	// Example using context:

	function MyObject() {}
	MyObject.prototype.onBoom = function() {
		// in this example, 'this' is set to 'obj'.
	};

	var obj = new MyObject();
	emitter.on('end-of-the-world', obj.onBoom, obj);

The poorly (but commonly) named off:


	// clears all listeners registered on emitter.
	emitter.off();

	// clears all listeners for 'some-event'.
	emitter.off('some-event');

	// removes the listener added with
	//    emitter.on('some-event', callback);
	emitter.off('some-event', callback);

	// removes the listener added with
	//    emitter.on('some-event', callback, context);
	emitter.off('some-event', callback, context);

	// removes all listeners registered with a context of context.
	emitter.off(null, null, context);
	// or
	emitter.clearListeners(context);

trigger (sometimes called emit or fire or notify):


	// All listeners registered for the 'end-of-the-world' event
	// will get called with alienSpacecraft as their first argument.
	emitters.trigger('end-of-the-world', alienSpacecraft);

once is another function that is commonly provided by Emitters:


	// Once behaves similarly to .on, but the listener is only
	// ever called once.
	emitter.once('some-event', function() {
		// this function will only be called once.
	});

	emitter.trigger('some-event');
	emitter.trigger('some-event');

Extra Features

This Emitter provides two extra features.

MetaEvents

The emitter will also trigger special events that you can listen to in certain circumstances. The event emitter in node does a similar thing, firing newListener and removeListener events at the appropriate time.

There are three meta events which are:

  • emitr.meta.AddListenerEvent, triggered when a listener is added.
  • emitr.meta.RemoveListenerEvent, triggered when a listener is removed.
  • emitr.meta.DeadEvent, triggered when an event is fired but no listeners receive it.

	// In this example, I use an AddListenerEvent metaevent to
	// create 'sticky' events behaviour for the ready event.

	function Document() {
		this.isReady = false;

		this.on(Emitter.meta.AddListenerEvent, function(addEvent) {
			if (this.isReady) {
				addEvent.listener.call(addEvent.context);
			}
		}, this);
	}
	Emitter.mixInto(Document);
	Document.prototype.makeReady = function() {
		this.isReady = true;
		this.trigger('ready');
	};

	var doc = new Document();

	doc.makeReady();

	// Even though makeReady was called before this 'on',
	// the listener will still be called.

	doc.on('ready', function() {
		console.log('ready now');
	});

Type Based Events

The Events themselves in normal usage are usually string identifiers and then a list of arguments, almost like an algebraic data type - a tag and then a tuple of data items. In an object language like javascript, it seems more natural to dispatch event objects instead and listen for them based on their type.


	function MouseEvent(x, y) {
		this.x = x;
		this.y = y;
	}

	emitter.on(MouseEvent, function(event) {
		// in here, event is the instance of MouseEvent that
		// we trigger the emitter with.
	});

	emitter.trigger(new MouseEvent(100, 99));

It obeys the Liskov Substitution Principle, so a listener will also get notified of events that are subclasses of the event type it is registered for.


	function ClickEvent(button, x, y) {
		MouseEvent.call(this, x, y);
		this.button = button;
	}

	ClickEvent.prototype = Object.create(MouseEvent.prototype);

	emitter.on(MouseEvent, function(event) {
		// in here, event is the instance of ClickEvent that
		// we trigger the emitter with.
	});

	emitter.trigger(new ClickEvent("right", 101, 100));