Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

on should be idempotent #4597

Closed
jfirebaugh opened this issue Apr 17, 2017 · 4 comments
Closed

on should be idempotent #4597

jfirebaugh opened this issue Apr 17, 2017 · 4 comments
Labels

Comments

@jfirebaugh
Copy link
Contributor

Like addEventListener, Evented#on (and Map#on with delegation) should be idempotent, and only do something if there wasn't already a listener for the given event type and callback.

For example, the sequence on('a', cb), on('a', cb), off('a', cb) should leave no cb's listening for a.

@areichman
Copy link

@jfirebaugh Using your example, if I don't call off('a', cb), I'm seeing on('a', cb) fire twice. Is that your expectation at the moment?

I'm seeing this behavior while trying to implement a style switcher. I'm calling map.setStyle() then reloading my custom sources and layers (using React state to remember which should be loaded). Some of my sources and layers add their own listeners (e.g. display popup on click), so I get duplicate listeners each time I switch styles.

@jfirebaugh
Copy link
Contributor Author

Yeah, I believe double firing is what will currently happen if you bind the same function instance to the same event multiple times. But what you're seeing isn't necessarily this issue. A common mistake is to accidentally bind multiple different functions instances (which happen to do the same thing), e.g. with an inline function (on('a', function(e) { ... })), arrow function (on('a', (e) => { ... })), or bind result (on('a', this.onFoo.bind(this))). Since in each of these cases it's a different function instance being passed to on each time, they won't be affected by what's proposed here.

@areichman
Copy link

In my case, it is a binded (bound?) function, but that's happening in the constructor of my class:

this.update = this.update.bind(this);

Then I create the event listener using:

map.on('click', this.update);

So I would expect the same function instance to be passed each time, correct? Without a fix for this issue in place, I can look at internally tracking whether the event listener has been created already.

@jfirebaugh
Copy link
Contributor Author

So I would expect the same function instance to be passed each time, correct?

Yes, provided there's only one instance of the class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants