2

I have a function that is used to send messages and that is called multiple times in a sec. But I want to call that function once a sec and delay other calls of that function with another 1-second of the previous call. So that only that function run in the background and called once in a second, no matters how many times it is called it will delay each call to one second ahead.

For example:

function foo(a) {
  console.log(a)
}
foo('one');
foo('two');
foo('three');

in the above example, foo is called three times within a sec but I want to have it called like after the 1 second it should return "one" after 2 seconds it should return 'second' and so on and it should be asynchronous.

How can I do this?

The technology I am using is Javascript.

Thanks

R. Richards
  • 24,603
  • 10
  • 64
  • 64
Piyush Zalani
  • 3,686
  • 1
  • 13
  • 29
  • 3
    There is a function in JavaScript called [`setTimeout()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) – Ibu Oct 31 '18 at 21:33
  • If I wrap the function in setTimeout to 1 sec then after one sec it will call all the function at the same time, it wont delay function to run once in a sec – Piyush Zalani Oct 31 '18 at 21:36
  • Why don't you wrap the set timeout in a function? – ca1c Oct 31 '18 at 21:37
  • Use a queue, and setInterval. – Keith Oct 31 '18 at 21:37
  • 1
    One term for this is a "debounce function". – ceejayoz Oct 31 '18 at 21:44
  • https://stackoverflow.com/questions/27078285/simple-throttle-in-js – epascarello Oct 31 '18 at 21:56
  • @epascarello, ceejayoz, No throttle and debounce is not a good idea, because I have to execute all the invocation of the function but with some delay in each execution, say a function is called 5 times then I want to run the algorithm of that function 5 times but with delay of 1 second with previous execution. like, run algorithm 1st time -> complete it -> wait for 1 sec -> run algorithm 2nd time -> complete it -> wait for 1sec and so on. – Piyush Zalani Nov 01 '18 at 10:52
  • Yes it is a good idea, you just need to rethink it.... If I get time, I will show you the basic idea. – epascarello Nov 01 '18 at 15:15

5 Answers5

1

Here is a simple queue system, it basically just pushes the functions onto an array, and then splice's them off every second.

const queue = [];

setInterval(function () {
  if (!queue.length) return;
  const f = queue[0];
  queue.splice(0, 1);
  f();
}, 1000);

function foo(a) {
  queue.push(function () {
    console.log(a)
  });
}
foo('one');
foo('two');
foo('three');
Keith
  • 22,005
  • 2
  • 27
  • 44
  • I don't want to call that function every second, Suppose it is already being called many times from somewhere else. I just want to make delay to those executions to not execute all call in the current second but execute it later after a second of previous execution. – Piyush Zalani Oct 31 '18 at 21:45
1

Well this is the first thing I came up with - perhaps it's crude.

var queuedUpCalls = [];
var currentlyProcessingCall = false;

function foo(a) {
  if (currentlyProcessingCall) {
    queuedUpCalls.push(a);
    return;
  }

  currentlyProcessingCall = true;
  setTimeout(function(){
    console.log(a);
    currentlyProcessingCall = false;

    if (queuedUpCalls.length) {
      var nextCallArg = queuedUpCalls.shift();
      foo(nextCallArg);
    }
  },1000);
}
foo('one');
foo('two');
foo('three');

For each call, if you're not currently processing a call, just call setTimeout with a delay of 1000ms. If you are processing a call, save off the argument, and when the setTimeout that you kicked off finishes, process it.


Somewhat improved answer using setInterval:

var queuedUpCalls = [];
var timerId;

function foo(a) {
  queuedUpCalls.push(a);

  if (timerId) {
    return;
  }

  timerId = setInterval(function(){
    if (!queuedUpCalls.length) {
      clearInterval(timerId);
      timerId = null;
      return;
    }

    var nextCallArg = queuedUpCalls.shift();
    console.log(nextCallArg);
  }, 1000);
}

foo('one');
foo('two');
foo('three');
pushkin
  • 9,575
  • 15
  • 51
  • 95
0

you could use this to run the main code first and then run some more code a little later.

function firstfunction() {
  alert('I am ran first');
  setTimeout(function(){ alert('I am ran 3 seconds later') }, 3000);
}
<button onclick="firstfunction();">click me</button>
ca1c
  • 1,111
  • 10
  • 23
  • What if I click that button 10 times in a second, that the function will be called 10 times after 3 seconds, but my scenario is to call a function in every x seconds of previous execution in asynchronous way. – Piyush Zalani Oct 31 '18 at 21:47
0
function foo(a)
{
    if (typeof foo.last == 'undefined')
        foo.last = Date.now();

    var now = Date.now();
    if (now - 1000 > foo.time)
        foo.last = now;

    setTimeout(function()
    {
        console.log(a);
    }, (foo.last += 1000) - now);
}

This will queue each console.log call with intervals of 1 second, the first call will also be delayed by 1 second.

Havenard
  • 27,022
  • 5
  • 36
  • 62
0

You could do this:

function foo() {
  console.log(“ran”);
}
setInterval(foo, 1000);

In the last line, writing foo() without parenthesis is intentional. The line doesn’t work if you add parentheses.

object-Object
  • 1,587
  • 1
  • 12
  • 14