deleteddeleted
deleteddeleted

Reputation: 155

Wait for execution to complete before executing again

I want to prevent my click handler from executing multiple times, however it is not working as expected. Is my approach in the right direction? I want this handler to get executed when user clicks on button just once. This handler can get executed again of course (after the execution has completed).

var init = false,
    i = 1;

$('button').on('click', function() {
  if (init) {
    return;
  }

  init = true;

  (function() {
    // this for loop is for example purposes, just to have something running
    for (var i = 0; i < 5000; i++) {
      $('.text').append(i)
    }
    init = false;
  }());

  $('.counter').html(i);
  i++
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">Button</button>
<div class="text"></div>
<div class="counter"></div>

Upvotes: 1

Views: 117

Answers (3)

deleteddeleted
deleteddeleted

Reputation: 155

After figuring out that the UI was being blocked, I looked into solutions to 'chunking' the loop into smaller loops, allowing the UI to become unblocked and other functions to be executed.

Chunked for loop

function loop(arr, fn, before, callback) {
    let index = 0,
        step = 50,
        stepTotal = step;

    before();

    (function chunk() {
        while(index < arr.length && index < stepTotal) {
            fn(arr[index], index);
            index++;
        }

        if (index < arr.length) {
            stepTotal+=step;
            setTimeout(chunk, 0);
        } else {
            callback();
        }
    })()
}

Upvotes: 0

guest271314
guest271314

Reputation: 1

Try setting button property disabled to true at beginning of init , using .hide() , .delay() , .show() , setting disabled property to false

var count = 1,
  max = 5000,
  init = function() {
    $(this).prop("disabled", true)
    .off("click.count");
    $(".counter").html(count);
    count++;
    $(this).hide(0, function() {
      for (var i = 0; i < max; i++) {
        $(".text").append(i);
      }
    }).delay(max / 2).show(function() {
      $(this).prop("disabled", false)
      .on("click.count", init)
    })
  };

$("button").on("click.count", init);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<button id="button">Button</button>
<div class="text"></div>
<div class="counter"></div>

Upvotes: 1

Norlihazmey Ghazali
Norlihazmey Ghazali

Reputation: 9060

Here try this solution.

At first we register click handler to button :

$('button').on('click', runThis );

And here the runThis() handler function :

function runThis() {
  // register off click handler on button
  $('button').off('click');    
  // loop over i
  for (var i = 0; i < 2000; i++) {
    $('.text').append('<br/>' + i);        
  }
  // if execution finish
  if (i == 2000) {
    // register back handler
    addBack();
  }
}

And here we on back the click handler on button :

function addBack() {
   $('button').on('click', runThis );
}

Upvotes: 1

Related Questions