I have been trying for hours remove event listener without any success.
Because of a test I have carried out I understood that the problem probably lies in listener reference.
Here is the code. I stripped and simplified everything for the clarity sake.
const COMPLETE = 'complete';
let dispatcher = new EventTarget;
class Template {
complete(e){
e.currentTarget.removeEventListener(COMPLETE, this.complete);
console.log('I run only once');
}
}
let child = new Template();
child.exe = function(){
dispatcher.addEventListener(COMPLETE, this.complete.bind(this));
}
child.exe();
dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
Of course in console you can read three times "I run only once".
The test I did involved extra variable 'functionReference' where I store the listener reference. Then it works.
let functionReference
const COMPLETE = 'complete';
let dispatcher = new EventTarget;
class Template {
complete(e){
e.currentTarget.removeEventListener(COMPLETE, functionReference);
console.log('i run only once');
}
}
let child = new Template();
child.exe = function(){
functionReference = this.complete.bind(this);
dispatcher.addEventListener(COMPLETE, functionReference);
}
child.exe();
dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
Now in console there is only once "I run only once".
What is happening? Why I can't remove that listener?
*****UPDATE / SOLUTION BELOW ***Many thanks to Teemu and amrender singh
Thank You amrender singh for explanation! And thank You Teemu for great idea and solution! Thank You so much for quick help! I haven't been stuck so much in years.
Below Teemu solution:
const COMPLETE = 'complete';
let dispatcher = new EventTarget;
class Template {
constructor(){
this.complete = (e)=>{
e.currentTarget.removeEventListener(COMPLETE, this.complete);
console.log('i run only once');
}
}
}
let child = new Template();
child.exe = function(){
dispatcher.addEventListener(COMPLETE, this.complete);
}
child.exe();
dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
Alternatively a reference to the listener can be stored and passed as a variable.
From MDN:
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
In the first example:
dispatcher.addEventListener(COMPLETE, this.complete.bind(this));
The bind creates a new function and attaches it as the handler. That is why you are unable to remove the event listener as the event listener you previously attached using bind is not same as your complete method.
In your second example:
functionReference = this.complete.bind(this);
dispatcher.addEventListener(COMPLETE, functionReference);
You are registering the new function returned by bind as listener and then removing it, since in both add/remove the listener is same that is why it is getting removed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With