UNPKG

gaga-js-utils

Version:

js tools

129 lines (93 loc) 3.15 kB
## 防抖和节流 防抖和节流可以说是一对好基友,也是前端面试的手写热点考题。防抖和节流其实都是在规避频繁触发回调导致大量计算,从而影响页面发生抖动甚至卡顿。简单的说将多次回调比如页面点击或ajax调用变为一次。防抖和节流的区别在于以第一次为准还是最后一次为准。 ## 需求 ### 1. 节流Throttle - 调用多次、只第一次调用有效 在一段时间内,不论触发多少次调用,都以第一次为准。 输入框补全提示,只需要每两秒补全一次。 用测试用例表示 ```js it("节流Throttle", (done) => { const { throttle } = require("../index"); // 定义一个Mock函数 const mockFn = jest.fn(); // 封装为节流方法 const fn = throttle(mockFn, 10); // 同步调用两次 fn(1); fn(2); setTimeout(() => { const calls = mockFn.mock.calls; // 断言 mock方法只调用一次 expect(calls.length).toBe(1); // 根据参数判断以第一次调用为准 expect(calls[0][0]).toBe(1); done(); }, 50); }); ``` ### 2. 节流Debounce 最后一次为准 在一段时间内,不论触发多少次回调,都已最后一次为准。 比如:以用户拖拽改变窗口大小,触发 resize 事件为例,会触发组件重新布局,这里面只有最后一次调用是有意义的。 ```js it("防抖Debounce", (done) => { const { debounce } = require("../index"); const mockFn = jest.fn(); // 封装一个防抖函数 const fn = debounce(mockFn, 10); // 连续两次调用 fn(1); fn(2); setTimeout(() => { const calls = mockFn.mock.calls; // 断言只调用一次 expect(calls.length).toBe(1); // 断言以最后一次调用为准 expect(calls[0][0]).toBe(2); done(); }, 50); }); ``` ## 功能实现 ### 节流 主要思路利用时间戳判断,每次调用判断和上一次调用的时间差异确定是否需要调用。 throttle实际是一个工厂函数,可以将一个函数封装为一个带有节流功能的函数。 ```js module.exports.throttle = (fn, delay) => { // 定义上次触发时间, isExecute: 在规定时间是否已执行,防止多次调用的二次执行 let last = 0, isExecute = 0; return (...args) => { const now = + Date.now(); console.log("call", now, last, delay); if (now > last + delay) { last = now; if ( !isExecute) { fn.apply(this, args); isExecute = 1; } } }; }; ``` ### 防抖 实现的话可以使用定时器执行函数,新调用发生时如果旧调用没有执行就清除之前的定时器。 ``` /** * 防抖Debounce */ module.exports.debounce = (fn, delay) => { let timer; return (...args) => { // 判断定时器是否存在,清除定时器 if (timer) { clearTimeout(timer); } // 重新调用setTimeout timer = setTimeout(() => { fn.apply(this, args); }, delay); }; }; ``` ## 测试 ![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/531a5dd783ac40bcae2b89717e9ce5bf~tplv-k3u1fbpfcp-watermark.image) OK 任务完成