Search code examples
javascriptunderscore.jslodash

How to execute functions with delay, underscorejs/lodash


Background

I have a JavaScript function that prints numbers to the screen. This function prints a lot of numbers, but I am using a screen as old as Alan Turing so it can't print the numbers so fast!

The solution? Throtlle/debounce/delay the prints using underscorejs or lodash.

Tentative

My first tentative was to use throttle.

let fun = num => {
  console.log(num);
};

let throttleFun = _.throttle(fun, 1000);

for (let i = 0; i < 10; i++) {
  throttleFun(i);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

But instead of printing all the numbers with a 1000ms of separation, it just calls the function every 1000ms, which causes it to only actually execute twice.

My next try, was to use debounce:

let fun = num => {
  console.log(num);
};

let debouncedFn = _.debounce(fun, 1000);

for (let i = 0; i < 10; i++) {
  debouncedFn(i);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Now, again, instead of printing the values with 1000ms of separation, debounce actually delays the execution of my function since it last executed by 1000ms, which causes it to only execute once.

Question

All the behaviors I previously mentioned are documented, and they are the same for both underscore and lodash.

My question here is:

  • Using one of the previous libraries (or another similar one), is there a way to print the arguments the function receives in the console with 1000ms of separation between them, using a similar function style?

Please note that while in this case the arguments happen to be numbers, in reality they can be strings, objects or any other thing without any co-relation whatsoever.


Solution

  • You can do it with the native setInterval function:

    let fun = num => {
      console.log(num);
    };
    
    let max = 10, i = 0;
    
    let timer = setInterval(() => {
      fun(i);
      i++;
      if (i === max) {
        clearInterval(timer);
      }
    }, 1000);
    

    If you want to use a underscore/lodash, you do do something like so:

    let fun = num => {
      console.log(num);
    };
    
    for (let i = 0; i < 10; i++) {
        _.delay(fun, 1000 * (i + 1), i);
    }