实现一个节流函数? 如果想要最后一次必须执行的话怎么实现?

// 节流就是在给定的time内代码会被执行一次
function throttle(fn, delay) {
  let prevTime = 0; //上一次fn开始执行的时间
  let timer; //为什么多次执行 throttle 后prevTime和timer还能保留原来的数据呢?因为这个节流函数用到了闭包,变量被保存在了内存中不被垃圾回收。
  return function (...args) {
    const now = Date.now();
    const restTime = delay + prevTime - now; // 剩余时间
    // 如果第二次执行超过delay了就立即执行
    // restTime > delay 是为了处理两次fn执行期间修改了系统时间的情况,
    // 比如把当前系统时间往过去调了十分钟,那么now其实是比prevTime小的,
    // 那么 restTime 就可能是一个比较大的数了.
    if (restTime <= 0 || restTime > delay) {
      console.log("第一次触发的位置在这");
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }
      fn.apply(this, args);
      prevTime = now;
    } else if (!timer) {
      // 这里就是为了处理1.5s停止触发的情况
      // 以1.5s为例,delay为1s,这个时候我们设置一个定时器
      // 让它在0.5s后执行
      // 这样在整个过程中,就是第0s, 第1s,第2s分别执行一次,共三次
      // 虽然我们是1.5s就停止触发了
      // 这样就保证了最后一次动作一直可以执行
      timer = setTimeout(() => {
        console.log("之后触发的位置在这");
        fn.apply(this, args);
        prevTime = Date.now();
      }, restTime);
    }
  };
}
 
// ================
// 测试用例
function func1(word) {
  console.time("s");
  let str = [1, 2, 3, 4, 5];
  for (let i = 0; i < 1000; i++) {
    str.push(i);
    for (let j = 0; j < 1000; j++) {
      str[i] = j;
      for (let k = 0; k < 100; k++) {
        str[k] = j;
      }
    }
  }
  console.log(word);
  console.timeEnd("s");
}
 
let func = throttle(func1, 3000);
for (let i = 0; i < 5; i++) {
  func("世界和平");
}
 
posted @ 2023-03-06 10:25  菌子乐水  阅读(193)  评论(0编辑  收藏  举报