// 节流就是在给定的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("世界和平"); }
标签:执行,节流,实现,timer,delay,let,now,prevTime,函数 From: https://www.cnblogs.com/shidawang/p/17182852.html