Git Product home page Git Product logo

mitt's Issues

Should not allow emitting the wildcard?

See tunnckoCoreLabs/dush#5. Because it will trigger listeners twice. See this reddit thread comment.

The simplest fix is to do something like that

    emit (name, a, b, c) {
      if (name !== '*') {
        (all[name] || []).map((handler) => { handler(a, b, c) });
        (all['*'] || []).map((handler) => { handler(name, a, b, c) })
      }
    }

the test case that i made for dush

test('should not allow emitting the wildcard (issue#5)', function (done) {
  var emitter = dush()

  emitter.on('*', function (name, a, b, c) {
    test.strictEqual(name, 'foo')
    test.strictEqual(a, 1)
    test.strictEqual(b, 2)
    test.strictEqual(c, 3)
  })
  emitter.on('foo', function (a, b, c) {
    test.strictEqual(a, 1)
    test.strictEqual(b, 2)
    test.strictEqual(c, 3)
  })

  emitter.emit('*', 4, 5, 6)
  emitter.emit('foo', 1, 2, 3)
  emitter.emit('*', 555)
  done()
})

Thanks !

I use a lot of code that you develop and open-source.
I never run into issues that cant be solved by re-reading the docs (and/or in rare cases the code) so I never open issues in here and am using this as a chance to.
I suspect there are many people like me :)

Thanks to @developit ( and all contributors ! ) for the great work !
Cheers 😄

ES modules build

I would like to be able to use Mitt from the browser like:

<script type=module>
  import mitt from 'https://unpkg.com/mitt/es.js';

  let emitter = mitt();
  ...
</script>

Would you be open to a build that that includes the export. Since this is using rollup that should be pretty easy I think.

[feature request] once handler

would u consider adding this or is it out of scope? Ive tried implementing it myself so I could send a PR, but my minifications skill are not that great ;)

best result i got was 214B which is exceeding ur goal

Uncaught TypeError: mitt is not a constructor

Hi!
Im trying to use mitt in our react project using typescript.
But I get this error in runtime:

Uncaught TypeError: mitt is not a constructor
    at eval (api.ts:11)
    at Object../packages/foo-api/api.ts (bundle.js:10804)
    at __webpack_require__ (bundle.js:672)
    at fn (foo.js:98)
    at eval (index.ts:5)
    at Object../packages/foo-api/index.ts (bundle.js:10817)
    at __webpack_require__ (bundle.js:672)
    at fn (bundle.js:98)
    at eval (Foo.view.tsx:15)
    at Object../packages/foo-ui/Foo.view.tsx (bundle.js:11779)

I'm using ut just like in your example

import * as mitt from 'mitt'
const emitter: mitt.Emitter = new mitt()

When debugging in Dev tools and check mitt it's an object, not a contructor.

Object {__esModule: true, default: function}
   default: function mitt(all )
   __esModule: true
   __proto__: Object

Am I doing something wrong?

Unable to use extend with mitt

Hey,
I noticed that after when I try to use extends in my TypeScript project, the all class stuff are just removed.

Also I need to use ugly hack to execute the constructor of mitt beacuse TypeError: mitt is not a constructor.

const mittConstructor = (mitt as any).default.prototype.constructor;
type ExampleClassEmitter = StrictEventEmitter<mitt.Emitter, IExampleEvents>;
class ExampleClass extends (mittConstructor as { new(): ExampleClassEmitter }) {}

So I need to do like this to get inheritance:

const mittConstuctor = (mitt as any).default.prototype.constructor;
class MittFix {
  constructor() {
    Object.entries(mittConstuctor()).forEach(([key, value]) => {
      this[key] = value;
    });
  }
}

class ExampleClass extends (MittFix as { new(): ExampleClassEmitter }) {}

That's because Mitt constructor returns an object { ... }, and 'this' is not used, but should be.

Regards,
TheAifam5

Question: do you want to make `once()` available?

One of the things I find useful about event emitters/signals is the ability to emit an event/signal only once.

I understand this library aims to have a super small footprint, but I do believe adding such feature would not add significant size to the final bundle.

With that being said, do you have interest in adding this feature? If so, I can attempt a PR.

Thank you.

Support emitting multiple arguments

Just like .emit('foo', 1, 2, 3). Initially thought for rest + spread but it adds around 50 bytes.
So I think it may be enough to have explicitly defined 3-4 arguments

That adds 4 bytes.

    emit(type, a, b, c) {
      list('*').concat(list(type)).forEach( f => { f(a, b, c); });
      return ret;
    }

Some faster implementations than node core's uses this tactic, but up to 6-8 args

TypeScript: Wildcard types did not make it into 1.1.3

Just looking at the source package of 1.1.3 and the release notes mention that the wildcard typing was added.

Unfortunately, it looks like 1.1.3 still has the old typing definition. Any chance you can trigger a release of 1.1.4 with the updated wildcard typing?

Bitwise operators question

Hello,

I'm here just to ask what is the main usage of the bit operators here? in the off function you're using >>> at line 40

all[type].splice(all[type].indexOf(handler) >>> 0, 1);

And in the old source code you used ~ also inside the off function at line 34

I just want to know why because I can't see a reason to use them and thank you in advance

Deduping handler registration

In the initial release of mitt a caller can register one handler multiple times for an event. For some use cases, though, duplicate registrations can be problematic. At the moment, mitt does not provide any APIs to avoid duplicate registration.

I see two straight forward ways of allowing consumers to avoid duplicate registration:

  1. Extend on() to take a dedupe parameter. When truthy, mitt would not register the handler if it's already present on all.
  2. Create a has() method that returns a Boolean indicating if a given handler has been registered for an event. Callers concerned about duplicate handlers can manually check before calling on().

Between the two I feel like 1 provide a more ergonomic API and would likely help keep byte count down.


Prior art

  • Element.addEventListener silently drops duplicate listener registrations.
  • EventEmitter.on states "[m]ultiple calls passing the same combination of eventName and listener will result in the listener being added, and called, multiple times."

UglifyJS Build Error

Hey guys, I opened an issue with React Boilerplate, but thought I'd open one here as well to see if you've ever come across problems uglifying this module installed via npm. Maybe there's a problem with the Webpack config and I just need to add something to make it play nice? Anyway, the boilerplate is one of the most popular boilerplates available for React and it yields a build error when Mitt is either a direct dependency, or any dependent packages are using Mitt.

Here are the steps to reproduce:

$ git clone --depth=1 https://github.com/react-boilerplate/react-boilerplate.git
$ cd react-boilerplate
$ npm run setup
$ npm run clean
$ yarn add mitt

Open react-boilerplate/app/containers/HomePage/index.js and add the following import:

import mitt from 'mitt';

Then,

$ npm run build

The given will be something like this:

ERROR in 1.673e1d9e06dc9452619e.chunk.js from UglifyJs
SyntaxError: Unexpected token punc «(», expected punc «:» [1.673e1d9e06dc9452619e.chunk.js:105,4]

Deploy fixes for Flow types to NPM

I noticed that #47 fixes some Flow types issues, but that the package.json is older than that PR. It's causing type errors for us via our svg-baker-runtime package which uses Mitt as a dependency. We're ignoring Mitt in our .flowconfig temporarily, but you might want to make sure it's been deployed.

Benefits?

Why to choose Mitt over native EventEmitter?
Just wondering

Strongly typed event names & values

I really like mitt, and the rewrite in TypeScript is a great step forward, but I wonder if we could go a bit further and allow strong typing of both the event names and their associated values.

Ideally, this would be an opt-in behaviour, meaning that by default mitt uses a string | symbol type for event names, and any for values. But passing an interface as a generic type to the constructor would tell mitt what events to expect and what values are associated, along with providing auto-completion in IDEs.

Hypothetical API:

interface MittEvents
{
  foo: number
  bar: string
  egg: {
    a: string[]
    b?: number
  }
  noarg: null
}

const emitter = mitt<MittEvents>()

emitter.on('foo', value => {
  // value has type `number`
})

emitter.on('bar', value => {
  // value has type `string`
})

emitter.on('egg', ({ a, b = 0 }) => {
  // a has type `string[]`
  // b has type `number` with a default value
})

emitter.emit('foo', 42)
emitter.emit('noarg', null)

// Check value type
emitter.emit('foo', 'not a number') // <- TS error

// Check allowed event names
emitter.emit('another', 42) // <- TS error

Such a typing system can be seen in action in vegemite, a state management library with a similar EventEmitter interface.

Alternative for removeAllListeners

I currently have an implementation using events and util.inherit (in the browser, so the npm versions), and would like to use mitt instead, however, I can't seem to figure out what I should use instead of removeAllListeners.

I guess I could keep a map of listeners myself, but that seems like duplicating what mitt does in the first place.

So far I have:

function DerivedHelper(mainHelper, fn) {
  this._emitter = mitt();
}

/**
 * Invoke all handlers for the given type.
 * If present, `"*"` handlers are invoked after type-matched handlers.
 *
 * @param {String} type The event type to invoke
 * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler
 * @memberOf mitt
 */
DerivedHelper.prototype.emit = function(type, data) {
  this._emitter.emit(type, data);
};

/**
 * Register an event handler for the given type.
 *
 * @param  {String} type Type of event to listen for, or `"*"` for all events
 * @param  {Function} handler Function to call in response to given event
 */
DerivedHelper.prototype.on = function(type, cb) {
  this._emitter.on(type, cb);
};

/**
 * Remove an event handler for the given type.
 *
 * @param  {String} type Type of event to unregister `handler` from, or `"*"`
 * @param  {Function} handler Handler function to remove
 */
DerivedHelper.prototype.off = function(type, cb) {
  this._emitter.off(type, cb);
};

/**
 * Detach this helper from the main helper
 * @return {undefined}
 * @throws Error if the derived helper is already detached
 */
DerivedHelper.prototype.detach = function() {
  // TODO: find a replacement for this
  this.removeAllListeners();
};

Thanks!

[question] off(*) behaviour

shouldnt it remove all listeners instead of only listeners attached with on('*', fn)? alternatively it would be good to have some destroy method to remove all listeners, whatsoever, that could be even achieved with emitter.off() (when called without arguments)

emit with multiple arguments

emit(type, ...a) {
  list('*').concat(list(type)).forEach( (f) => { f.apply(null, a); });
}

this seems it would be backwards compatible and support multiple arguments

"*" listeners may fire more than once.

If you want to only target "*" listeners and do emitter.emit("*", "stuff here"), those listeners will actually fire twice. Checking for that specific value before firing the "*" listeners would fix that.

Support chaining

It would be cool and is already some habit for some devs.

const mitt = require('mitt')
const emitter = mitt()
emitter.on('foo', console.log).on('bar', console.log).emit('foo', 123)

Include dist files

It seems currently the dist files aren't in the repo nor in the release zip.

Can you include them in the next release?

Why use slice?

(all['*'] || []).slice().map((handler) => { handler(type, evt); });
Why use slice?

Restrictions for the event name

This code will produce an exception:

const mitt = require("mitt")

const emitter = mitt()

emitter.on('constructor', e => console.log(1))
emitter.emit('constructor', {})

You may want to filter all those native methods out, or use a different approach of collecting the events.

Unsubscribe to all the listener

Hello,

should there be a method to remove all listeners of the emitter, to save performance?

I have an example case when we initialize a component, and the component needs to use the event emitter, and pass it to other function to listen to the component event:

// component.js
componentInit() {
  method.init(emitter);
}

// method.js
init (emitter) {
  emitter.on('something', doSomething);
}

Then, when the component is about to be destroyed, should the emitter be "cleaned up" so the method won't have to preserve the event listener anymore? For ex:

// component.js
componentDestroy() {
  emitter.off('*');
}

Publish latest changes please

It appears that there are some valuable changes in master. Are there bugs or issues preventing a release? I would love to see them published as a new version.

Thanks!

Wildcards to match segments?

Love seeing a new entry in the space for pubsub/events! Definitely something I keep thinking about.

Have you considered adding support for wildcards to match segments within an event as opposed to being used as a catch-all?
I believe postaljs does this with the # and * characters. Probably only need * to keep things minimalistic, unless there's a reason to differentiate matching one vs. many segments.

Testing

Isn't just enough to not use babel and etc? Why we need this and ES6 syntax and imports at all. It is just overhead. With that we can just remove babel from deps and they will look more clean.

/cc @developit

expose `all`

I think...

off(type) should remove all handlers for the given type

off() without arguments should just clear the all object completely

OR...

you can just expose all! it'll only be an addition of 4 chars, and I won't bother you anymore (or at least that's my story) ;P

Listen for events that happened before the listener is created.

Hey @developit,

this is a really neat library. I was wondering if it is possible to have a listener fire immediatly if it is attached to an event that already happened? It did not work for me, so is it no supported, or did I do it wrong?

For example I would like to fire an event once the animation library is loaded, so that I can start all animations afterwards, no matter where they are defined.

Thanks for your help.

TransformError in react-native

I believe some babel presets within mitt's package.json are causing following error when used in react-native

NOTE: adding those preset into project itself fixes the issue, but I'm not entirely sure if this it is a good solution to force presets? And it would be good to find out where and how mitt needs these to weight everything.

Loving the project so far <3 I converted my personal project to use mitt alongside slightly altered version of smitty (https://github.com/tkh44/smitty) and it seems much cleaner / easier compared to redux so far, great job 👍

Error received in react native v0.40, mitt 1.0.0

Imgur

Clean up repo root

  • Auto-generate (and gitignore) typings.json during build via package-to-typings
  • move mitt.d.ts into src/ (it's still included in the npm package)
  • Move .babelrc into tests/ since that's the only place it's used
  • gitignore yarn.lock
  • remove example.js (started in #37 - should be in the readme instead)

/cc @tunnckoCore

Benefits?

Why methods don't rely on this is a benefit?

typescript

Nice little lib. You make extra effort to document the parameters types.

How about typescript ?

if play with array's methods

// impl
function mitt() {
    all = [];
    return {
        on: (name, handler) => all.push(n => ~['*', n].indexOf(name) ? handler : _ => _),
        off: (name, handler) => all = all.filter(h => h(name) !== handler),
        emit: (name, args) => all.map(h => h(name)(name, args))
    };
}


//tests
const t = mitt();

const handler1 = (name, args) => console.log(name, args);
const handler2 = (name, args) => console.log(name, args);

t.on('*', handler1);
t.on('hello', handler2);

t.emit('hello', {
    a: 1
});

t.emit('test', {
    a: 2
});

t.off('*', handler1);
t.off('hello', handler2);

t.emit('hello', {
    a: 3
});

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.