3

I'm trying to create a function which is executed by a keypress and disabled for a specific time after execution.

function do_something() {
    console.log('lorem ipsum');
}

document.onkeypress = function(e) {
  if (e.keyCode == '32') {
    do_something();
  }
}

Is there any way to disable it for (let's say) 2 seconds after every execution?

6 Answers6

4

Yes, there is a way: use a Timeout to temporally set a boolean to certain value and then check it's value before calling do_something().

Example:

let cooldown = false;
const RECHARGE_TIME = 2000; //ms

function do_something() {
    console.log('lorem ipsum');
}

document.onkeypress = function(e) {
    if (!cooldown && e.keyCode == '32') {
        do_something();
        startCooldown();
    }
}

function startCooldown() {
    cooldown = true;
    setTimeout (function(){ cooldown = false}, RECHARGE_TIME);
}

EDIT: as Mosè Raguzzini noted: Depending on how important accuracy is, maybe this isn't the best method, since (as you can see here) it can be inacurate.

dquijada
  • 1,697
  • 3
  • 14
  • 19
  • setTimeout is not accurate and can fire later in the page. If execution is exact time based it is not reliable: https://stackoverflow.com/questions/21097421/what-is-the-reason-javascript-settimeout-is-so-inaccurate – Mosè Raguzzini Dec 18 '18 at 17:37
  • Just tested it out and it's actually pretty inaccurate, true. Of course, that's not necessarily important, but it's worth noting – dquijada Dec 18 '18 at 17:49
2

Try that, is a very simple and straightforward solution:

var firstExecution = 0; // Store the first execution time
var interval = 2000; // 2 seconds

function do_something() {
    // current date
    var date = new Date();
    var milliseconds = date.getTime(); 
    if((milliseconds - firstExecution) > interval){
      firstExecution = milliseconds;
      console.log('lorem ipsum');
    } else {
      console.log('too early');
    }
}

document.onkeypress = function(e) {
  if (e.keyCode == '32') {
    do_something();
  }
}
Mosè Raguzzini
  • 15,399
  • 1
  • 31
  • 43
0

A very silly answer would be to sleep javascript execution for a specific time.

function sleep(delay) {
  var start = new Date().getTime();
  while (new Date().getTime() < start + delay);
}

Then

document.onkeypress = function(e) {
  if (e.keyCode == '32') {
    do_something();
    sleep(2000);
  }
}

I said silly because it stop your entire script for a specific time, you may not need that behavior!

sadrzadehsina
  • 1,331
  • 13
  • 26
  • 1
    This is much worse than `silly`. You are running cpu cycles as fast as you can to do precisely nothing. It will make the entire interface laggy, just to do something that is easy to do in a better way. You should **never** use this code. – Mark Dec 18 '18 at 17:28
  • @MarkMeyer so let us know your solution then – sadrzadehsina Dec 18 '18 at 17:29
  • There's no reason for me to post a solution, there are several already posted to this thread. – Mark Dec 18 '18 at 17:30
  • @MarkMeyer I believe all of them blocks the entire app for a specific time, actually there is no other way to prevent a function call – sadrzadehsina Dec 18 '18 at 17:31
  • That's not true. setTImeout is queued with an async callback. It doesn't block the thread. That's the whole point of async code in javascript. It's very easy to test. – Mark Dec 18 '18 at 17:32
  • setTimeout is not accurate and can fire later in the page. If execution is exact time based it is not reliable: https://stackoverflow.com/questions/21097421/what-is-the-reason-javascript-settimeout-is-so-inaccurate – Mosè Raguzzini Dec 18 '18 at 17:38
  • There is no need to block the entire app, store the only data you need (last execution) and the rest can be checked in runtime – Mosè Raguzzini Dec 18 '18 at 17:39
0

Some thing like that, execution will be disable for 5s

var lastClicked = 0;
document.onkeypress = function(e) {
  var now = new Date();
  if (now - lastClicked > 5000) { //set a 5s  delay
    lastClicked = now;
    if (e.keyCode == '32') {
      do_something();
    }
  }
}

function do_something() {
  console.log('lorem ipsum');
}
Ahmed Ghoniem
  • 661
  • 1
  • 8
  • 15
-1
var timeout = false; //Control variable
var miliseconds = 2000; //Time in miliseconds for the function to enable again

function do_something() {
    if(timeout) return alert("Function disabled");
    console.log('lorem ipsum');
    timeout = true;
    setTimeout(function() { timeout = false }, miliseconds);
}

document.onkeypress = function(e) {
  if (e.keyCode == '32') {
    do_something();
  }
}
Valentin Garcia
  • 485
  • 6
  • 17
  • I believe it should really prevent the do_something function from happening, instead of it returning. Yes, I know it works exactly the same, just conceptually – dquijada Dec 18 '18 at 17:25
  • I see your point, but this way it doesn't matter where is 'do_something()' called it will respect the timeout that's why – Valentin Garcia Dec 18 '18 at 17:28
  • Hmm, true, I'm not sure if he wants to disable the function or they key event – dquijada Dec 18 '18 at 17:31
  • notice also setTimeout is not accurate and can fire later in the page. If execution is exact time based it is not reliable: https://stackoverflow.com/questions/21097421/what-is-the-reason-javascript-settimeout-is-so-inaccurate – Mosè Raguzzini Dec 18 '18 at 17:38
-1

Lodash has throttle for this purpose.

jorbuedo
  • 2,041
  • 1
  • 8
  • 20