Reputation: 5153
I have an event listener that is in a function. Both the listener and the emitter are in the same function.
When the event fires, a variable is incremented. So far so good. But when I call the function several times, the listener is triggered several times in the same function call.
var test = function() {
var completeStatus = 0;
$(document).on('gt', function() {
console.log(++completeStatus);
});
$(document).trigger('gt');
}
test();
test();
test();
It expect it to output 1 three times as the function is called three times. But it outputs:
0
1
0
2
1
Why is that and how to obtain the desired behaviour?
Here's a jsfiddle to try it out.
Upvotes: 1
Views: 546
Reputation: 5153
An other way would be to generate unique events and handler each time the function is executed:
var test = function() {
var completeStatus = 0;
var uniqid = Math.random().toString(36).slice(-8);
$(document).on('gt' + uniqid, function() {
console.log(++completeStatus);
});
$(document).trigger('gt' + uniqid);
}
test();
test();
test();
But what about performance implications? Is there any advantage/disadvantage using this approach?
Upvotes: 0
Reputation: 384
As mentioned in the above replies .on()
adds event listener, so in your example its added 3 times.
In addition to the earlier answer it would be good to avoid adding multiple listeners as it could lead to memory leaks, if you fail to remove them. So you could try this solution which removes the event listeners before adding again.
var test = function() {
var completeStatus = 0;
var GT_EVT = 'gt';
$(document).off(GT_EVT).on(GT_EVT, function() {
console.log(++completeStatus);
});
$(document).trigger(GT_EVT);
}
Upvotes: 1
Reputation: 2234
Because you are using $(document).trigger('gt'); so it's initiating trigger event in all document event that's why increasing the call of function returning output like
0 //from first function call
1 0 //from second function call
2 1 0 //frm third function call
.... and so on
Solution :
var test = function() {
var completeStatus = 0;
var pageInitialized = false;
$(document).on('gt', function() {
if(pageInitialized) return;
console.log(++completeStatus);
pageInitialized = true;
});
$(document).trigger('gt');
}
test();
test();
test();
Upvotes: 2
Reputation: 288100
.on()
adds event listers, it doesn't replace previous ones:
Attach an event handler function for one or more events to the selected elements.
When an element has multiple event listeners, the order is well defined:
Event handlers bound to an element are called in the same order that they were bound.
And .trigger()
executes them all in that order:
Execute all handlers and behaviors attached to the matched elements for the given event type.
Therefore,
The first time you call test
, you add an event listener with completeStatus = 0
, and you trigger it. So you get
0
The second time you call test
, the previous event listener has completeStatus = 1
. Then you add a second event listener with completeStatus = 0
, and you trigger both. So you get
1 // From the first event listener
0 // From the second event listener
The third time you call test
, the first event listener has completeStatus = 2
, and the second one has completeStatus = 1
. Then you add a third event listener with completeStatus = 0
, and you trigger them all. So you get
2 // From the first event listener
1 // From the second event listener
0 // From the third event listener
Upvotes: 2