使用Lodash Throttle时,如何确保两个请求到达服务器的间隔?

使用 lodash throttle 函数时,我遇到了一种情况,需要确保两个网络请求到达服务器时有足够的时间间隔。
由于网络延迟的存在,间隔一秒发送的两次请求,可能同时到达服务器。
我希望第二次请求在第一次请求完成后的一秒再次发起,以确保它们到达服务器的间隔不小于一秒。
是否可以通过 lodash 中现有的 throttle 函数实现这个目标,或者是否有其他推荐的方法?

// 为了方便观测, 间隔设置为10秒
export default () => {
  const sendRequest = () => new Promise((resolve) => setTimeout(resolve, 3000)) // 3s

  const throttledRequest = throttle(
    () => {
      console.log(now(), '执行请求')
      sendRequest().then(() => console.log(now(), '获得结果'))
    }, 10000, { leading: true, trailing: true } // 10s
  )
  const triggerRequest = () => {
    console.log(now(), '触发操作')
    throttledRequest()
  }
  return <button onClick={triggerRequest}>click</button>
}
假设00:00时双击按钮, 第一次请求立即触发, 并在第00:03得到第一次结果;
当前在第00:10发送第二次请求, 00:13得到第二次结果;
希望在第00:13发送第二次请求, 00:16得到第二次结果.(00:03回调后等10秒开始执行第二次请求)
阅读 779
1 个回答

答案是不能,因为 _.throttle 并不关心执行结果,也不提供介入调度过程的参数,要想实现那样的效果,只能在原函数上面下功夫,不如另起炉灶。

/**
 * @param {(...args: any[]) => Promise<any>} fn 被节流的函数
 * @param {number} [duration] 节流间隔
 * @param {Function} [resolver] 用于接收函数执行结果的回调函数
 * @param {Function} [rejector] 用于处理失败请求的回调函数
 * @return {() => void} 返回一个函数,执行该函数即可终止节流函数继续进行
 */
function asyncThrottle(
  fn,
  duration = 1e3,
  resolver = () => {},
  rejector = () => {}
){
  let timer = Number.MIN_VALUE;
  let keepGoing = true;

  return function(...args){
    const trigger = () => {
      fn.call(this,...args).then((res) => {
        if(keepGoing){
          timer = setTimeout(trigger);
        }
        resolve(res);
      }).catch(err => {
        if(keepGoing){
          timer = setTimeout(trigger);
        }
      });
    }
    trigger();
    return () => {
      clearTimeout(timer);
      keepGoing = false;
    };
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进