我可以在不放弃 JS 中的函数调用的情况下限制函数吗?

Can I throttle a function without dropping function calls in JS?

我需要一个函数在一个函数调用和另一个函数调用之间有一定的时间间隔,这与油门的作用非常相似,但我需要所有的函数调用都参与进来。

让我解释一下:

让我们假设我们在函数 foo 上设置了 10 秒的限制,并且有一个调用 foobar 的事件。 该事件被触发 3 次,每 5 秒一次。只有第一个和最后一个会参加,中间的会被忽略。

正常油门:

[event]--5s--[event]--5s--[event]
[foo]---------10s---------[foo]

我需要的是事件一直监听,但是比上一个晚10秒

[event]--5s--[event]--5s--[event]
[foo]----------10s--------[foo]---------10s--------[foo]

有什么想法吗?我考虑过节流阀和去抖器,但 none 它们适合我需要做的事情。

这很容易做到。只需创建一个函数对象数组,每 10 秒拉出最旧的一个并执行它。

    const queue = []
    
    function rateLimit(fn) {
      queue.push(fn)
    }
    
    setInterval(() => {
      const nextFn = queue.shift() // remove the first function, and return it.
      if (nextFn) nextFn() // execute the first function if it exists.
    }, 1000) // Your interval in milliseconds. Set to 1s for testing.
    
    
    rateLimit(() => console.log('A'))
    rateLimit(() => console.log('B'))
    rateLimit(() => console.log('C'))

您可以添加一些逻辑来在队列为空时清除间隔,并在有新项目进入时重新启动它,这样如果没有等待,第一个调用总是立即发生。但我留给你做练习。

如果有人感兴趣,我使用了 Alex Wayne 的答案并添加了一些逻辑以更好地控制他提到的时间间隔。

const queue = []
var intervalExecution

function rateLimit(fn) {
  queue.push(fn)
  if (queue.length && !intervalExecution) {
    intervalExecution = setInterval(() => {
      const nextFn = queue.shift()
      if (nextFn) {
        nextFn()
      } else {
        clearInterval(intervalExecution)
        intervalExecution = undefined
      }
    }, 1000)
  }
}

rateLimit(() => console.log('test'))
rateLimit(() => console.log('test'))
rateLimit(() => console.log('test'))
rateLimit(() => console.log('test'))