javascript jquery callback accumulates

858 views Asked by At

Issue: Each time div.a is clicked, the number of callbacks when div.b is clicked,accumulates by 1.

var $=jQuery;
$(function(){
   $("div.a").click(function(){cbf(trgmsg);});
});
function trgmsg(){
   alert($.now());
}
function cbf(cb){
   $("div.b").click(function(){cb()});
}

Result:
click div.a once and click div.b => alert() pops-up;
if i click div.a again and click div.b => alert() pops-up twice consecutively;
if i click div.a another time and click div.b => alert() pops-up three times consecutively;
..and so on

I have No idea what the cause of the problem is or if its simply my misunderstanding/misuse of callback functions in JS. Any insights and/or advice will be greatly appreciated. thanks

4

There are 4 answers

4
Brad Christie On

What you have now (refactored) looks like:

(function($){
  $(function(){
    function trgmsg(){
      alert($.now());
    }
    $('div.a').click(function(){
      // every time `div.a` is clicked a new click event is
      // attached to `div.b`.
      $('div.b').click(function(){ // maybe use `.one()` instead of `.click()`?
        cb();
      });
    });
  });
})(jQuery);

You may want to use .one() so after it binds it's only executed once. Or else you need to elaborate on what the actual goal is and see if that can be solves differently.

0
Robert Byrne On

If you just want to call the supplied function against div.b, when div.a is clicked, this might work for you

var $=jQuery;
$(function(){
   $("div.a").click(function(){cbf(trgmsg);});
});
function trgmsg(){
   alert($.now());
}
function cbf(cb){
   $("div.b")[0].apply(cb);
}
2
hyphrend On

You are attaching multiple click events onto div.b. So every time you click on div.a it is attaching another click event onto div.b so when div.b is clicked each of it's click events are fired. You can try setting a flag that says a click has already been registered.

var $=jQuery;
var flag = 0;
$(function(){
   $("div.a").click(function(){cbf(trgmsg);});
});
function trgmsg(){
   alert($.now());
}
function cbf(cb){
   if (!flag) {
       flag = 1;
       $("div.b").click(function(){cb()});
   }
}

Although I'm not quite sure what your using this for so that may not be your desired functionality.

0
AlienWebguy On

Quickest fix for your code without a refactor is to just unbind and re-bind.

var $=jQuery;
$(function(){
   $("div.a").click(function(){cbf(trgmsg);});
});
function trgmsg(){
   alert($.now());
}
function cbf(cb){
   $("div.b").off('click').click(function(){cb()});
}