简体   繁体   English

即使在 window 之后,如何使用油门限制通话?

[英]How can I limit the call with throttle even after the window?

I want to limit the call of function not more than once in 3s.我想在 3 秒内限制 function 的调用不超过一次。 but hope it can be invoked at first and delay all others after the wait.但希望它可以首先被调用并在等待后延迟所有其他人。 My use case is, limit the sending requests and then batch all on in the waiting to third party services.我的用例是,限制发送请求,然后在等待第三方服务时批量处理。 but not for the first call, it's a pain to wait for the first call.但不是第一个电话,等待第一个电话很痛苦。

so I made a throttle with lodash like this所以我像这样用lodash做了一个油门

const maxThrottle = _.throttle(() => console.log(new Date()), 3000, { trailing: true, leading: true })

and the calls are:电话是:

console.log('start: ', new Date())
maxThrottle()
await setTimeout(100)
maxThrottle()
await setTimeout(3000)
maxThrottle()

what I expected:我的预期:

start:  2022-09-04T06:58:01.099Z
2022-09-04T06:58:01.100Z
2022-09-04T06:58:04.104Z
2022-09-04T06:58:07.104Z

actual:实际的:

start:  2022-09-04T06:58:01.099Z
2022-09-04T06:58:01.100Z
2022-09-04T06:58:04.104Z
2022-09-04T06:58:04.214Z  // it is violating the speed of service which I want to avoid.

how can I do it with throttle?我怎么能用油门呢? is it possible?可能吗?

I can achieve the behavior with this code:我可以使用以下代码实现该行为:

function limitSpeed(fn: () => void, wait: number) {
  let calledAt: number | null
  let promise: Promise<void> | null
  return () => {
    const timeLeft = calledAt ? wait - (Date.now() - calledAt) : 0
    if (promise)
      return

    if (timeLeft <= 0) {
      calledAt = Date.now()
      fn()
    } else {
      promise = setTimeout(timeLeft).then(() => {
        calledAt = Date.now()
        fn()
        promise = null
      })
    }
  }
}

const maxThrottle = limitSpeed(() => console.log(new Date()), 3000)
console.log('start: ', new Date())
maxThrottle()
await setTimeout(100)
maxThrottle()
await setTimeout(3000)
maxThrottle()

while(true) {
  maxThrottle()
  await setImmediate()
}

result:结果:

start:  2022-09-04T07:22:13.621Z
2022-09-04T07:22:13.622Z
2022-09-04T07:22:16.630Z
2022-09-04T07:22:19.629Z
2022-09-04T07:22:22.628Z
2022-09-04T07:22:25.627Z
2022-09-04T07:22:28.626Z
2022-09-04T07:22:31.625Z
2022-09-04T07:22:34.624Z
2022-09-04T07:22:37.623Z
2022-09-04T07:22:40.622Z
2022-09-04T07:22:43.621Z
2022-09-04T07:22:46.621Z
2022-09-04T07:22:49.620Z
2022-09-04T07:22:52.619Z
2022-09-04T07:22:55.618Z
2022-09-04T07:22:58.617Z
2022-09-04T07:23:01.616Z
2022-09-04T07:23:04.615Z
2022-09-04T07:23:07.614Z
2022-09-04T07:23:10.613Z
2022-09-04T07:23:13.613Z
2022-09-04T07:23:16.613Z
2022-09-04T07:23:19.613Z
2022-09-04T07:23:22.613Z
2022-09-04T07:23:25.613Z
2022-09-04T07:23:28.613Z
2022-09-04T07:23:31.613Z
2022-09-04T07:23:34.613Z
2022-09-04T07:23:37.613Z
2022-09-04T07:23:40.613Z

It seems it is a bug of lodash .看来这是lodash的错误。 It is working perfect with underscore .它与underscore完美配合。 After replacement of underscore , the problem has gone.替换underscore后,问题消失了。 I guess lodash doesn't handle the case of throttle after the trailing.我猜lodash不处理尾随后油门的情况。 It will trigger immediately without wait with leading=true .它将立即触发,无需等待leading=true

As of Sep 2022, lodash is no longer maintaining for two years.截至 2022 年 9 月, lodash不再维护两年。 So I prefer switching to underscore if you have the same issue.所以如果你有同样的问题,我更喜欢切换到underscore

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM