【问题标题】:Call a function max once in a sec每秒调用一次函数 max
【发布时间】:2018-10-31 21:31:16
【问题描述】:

我有一个用于发送消息的函数,它在一秒钟内被调用多次。 但是我想每秒调用一次该函数,并将该函数的其他调用延迟上一个调用的另外 1 秒。 这样只有该函数在后台运行并在一秒钟内调用一次,无论调用多少次,它都会将每次调用延迟到一秒。

例如:

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

在上面的例子中, foo 在一秒钟内被调用了 3 次,但我希望它在 1 秒后被调用,它应该在 2 秒后返回“一”,它应该返回“秒”等等,它应该是异步。

我该怎么做?

我使用的技术是 Javascript。

谢谢

【问题讨论】:

  • JavaScript中有一个函数叫做setTimeout()
  • 如果我将 setTimeout 中的函数包装为 1 秒,然后在一秒后它会同时调用所有函数,它不会延迟函数每秒运行一次
  • 为什么不将设置的超时时间包装在一个函数中?
  • 使用队列,并设置间隔。
  • 对此的一个术语是“去抖动功能”。

标签: javascript


【解决方案1】:

嗯,这是我想出的第一件事——也许它很粗糙。

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');

对于每个呼叫,如果您当前没有处理呼叫,只需拨打setTimeout 延迟1000ms。如果您正在处理呼叫,请保存参数,当您启动的 setTimeout 完成时,处理它。


使用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');

【讨论】:

    【解决方案2】:

    您可以使用它先运行主代码,然后再运行更多代码。

    function firstfunction() {
      alert('I am ran first');
      setTimeout(function(){ alert('I am ran 3 seconds later') }, 3000);
    }
    <button onclick="firstfunction();">click me</button>

    【讨论】:

    • 如果我在一秒钟内单击该按钮 10 次,该函数将在 3 秒后被调用 10 次,但我的方案是在以前执行的每 x 秒以异步方式调用一个函数.
    【解决方案3】:

    这是一个简单的队列系统,它基本上只是将函数推送到一个数组上,然后每秒将它们拼接起来。

    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');

    【讨论】:

    • 我不想每秒都调用那个函数,假设它已经从其他地方被调用了很多次。我只想延迟这些执行,以便在当前秒内不执行所有调用,而是在前一秒执行后稍后执行。
    【解决方案4】:
    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);
    }
    

    这将使每个console.log 呼叫以 1 秒的间隔排队,第一个呼叫也将延迟 1 秒。

    【讨论】:

      【解决方案5】:

      你可以这样做:

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

      在最后一行中,不带括号的 foo() 是有意的。如果添加括号,该行将不起作用。

      【讨论】:

        猜你喜欢
        • 2011-11-06
        • 2011-03-09
        • 1970-01-01
        • 2018-05-17
        • 2018-02-16
        • 2023-03-16
        • 2018-10-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多