-
Notifications
You must be signed in to change notification settings - Fork 7
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
binding the same handler to the same event with once() can have unexpected results #7
Comments
Heya! Thanks for the report. I think problems mainly come from
Mainly, I don't want to rely on emitter.on('foo', function (a, b, c) {
console.log(a, b, c) // => 1, undefined, undefined
console.log(arguments.length) // => 3, it should be 1
})
emitter.emit('foo', 1) |
Actually, @nihlton, I can't get what's your problem exactly. That example is not full. |
It's a tricky problem to be sure. Re: 'this' just my humble opinion, but I think it's ok within once() because it's within a function dush entirely owns/creates/destroys. Doesn't impact including application space. |
When I have time, I'll add a fiddle to demonstrate the issue |
Okey, thanks. Is this test proving something? test('temp', function (done) {
var emitter = dush()
var myObject = null
let tokenPromise = () => {
if(myObject) {
return new Promise((resolve) => {
resolve(myObject.getToken() + ' ok!')
})
}
return new Promise((resolve) => {
emitter.once('MY_OBJECT_CREATED', () => {
myObject = {
getToken: () => Math.random() * 100
}
resolve(123)
})
})
}
var promise = tokenPromise()
emitter.emit('MY_OBJECT_CREATED')
promise.then(function (res) {
test.strictEqual(res, 123)
emitter.emit('MY_OBJECT_CREATED')
return tokenPromise().then(function (val) {
console.log('val1', val)
emitter.once('MY_OBJECT_CREATED', () => {
myObject = {
getToken: () => 555
}
})
emitter.emit('MY_OBJECT_CREATED')
return tokenPromise().then(function (value2) {
console.log('val2', value2) // => 555 ok!!
// emitter.emit('MY_OBJECT_CREATED')
done()
})
})
}, done).catch(done)
}) I don't see any problems. |
so it looks like you fixed it! i tried to write up an example with the current version and couldn't reproduce. good work. ...but just to demonstrate, I took the version from a week ago and put together this:
You would expect to see "token" in the console three times, but it only appears twice. |
also, just my two cents, but this isn't ideal: fn.sourceString = handler.toString(); what if i'm using 'sourceString'? or what if i'm not expecting any additional properties on the handler? just my opinion, but you shouldn't modify the handlers passed to you... but its your show :) thanks for looking into the issue. |
tokenPromise().then((token)=>{
console.log(token)
})
tokenPromise().then((token)=>{
console.log(token)
})
tokenPromise().then((token)=>{
console.log(token)
})
myObject = {
getToken: ()=>{
return 'token'
}
} thsi is totally wrong, and is absolutely expected to not work. Maybe go learn more for the promises, don't know. As about
yea, i'm not agree with that but that's easiest and smallest solution. If any problems appear anyone can come and report. |
lol ok dude. best of luck! |
@nihlton i'm thinking to change it to some more private like |
renaming "sourceString" to "__sourceString" so it won't conflict about #7 (comment) #7
this is just my opinion - the problem isn't the name, the problem is that you're still modifying the call back. A) its unexpected. if it broke something, it could take a while to figure out what is adding the extra property to the function object. B) its dirty. you might need to amend this - "Clean: Does not mess with DOM or anything." C) there are better ways. I am happily using the suggested fix from my first comment and have stopped pulling updates from this repo. |
For example? Don't want to use
Probably, but it is a lot harder and props with Very good principle is to do things as easy as possible and without too much assumptions. If user want to break something, let him break it if he want so much, but he also has the opportunity to not do that.
It's not. And still, it not mess with DOM. |
Why? Because you've heard 'using this is bad'? or do you have an actual reason?
That is fine for methods and properties that you own and control, but you're modifying a function which is passed to you by the user. it doesn't matter what you name the property, you're modifying someone else's function.
I would say modifying a function owned by the user would violate this. I think most people would. look, its your show, your project. this is just my opinion. do what you want. |
No. I'm not here from yesterday :) Actually, it's not bad, just most people don't know how to work with it and can't understand it clearly. I'm strong user of I just don't need prototypes anymore, since everything can use robust plugin architecture and everything is just a plugin or "smart plugin" - maybe we should call this "plugin inheritance", haha. Anyway. If anyone has a problem with that specific property, it's okey to come and report. Another thing can be to rename it to some shitty hash. Also user should pass function, not object or etc. Adding properties to function is also not so common thing, imo? |
I haven't investigated to precisely determine the mechanism of the bug, but the behavior i saw was that binding the same handler to the same event with once multiple times would remove the wrong handler after firing.
so for example, you have an object which provides a token: myObject.getToken(), but my object is instantiated by an asynchronous process, you might write code like:
multiple calls to tokenPromise results in the wrong handlers being unbound by once, i believe to confusion around the value of 'fn' within the once() method.
this seems to resolve the issue:
The text was updated successfully, but these errors were encountered: