Open cjfff opened 5 years ago
今天来梳理一下 JavaScript 中 防抖与节流
它们 两者 的目的都是为了 限制 某些事件监听的回调过于频繁的触发而进行的优化
比如:
window对象的 resize, scroll 事件 拖拽时的 mousemove 事件 文字输入、自动完成的 keyup 事件
概念
当调用动作过n毫秒后,才会执行该动作,若在n毫秒内重复执行,则会重新计时, 只执行最后一次动作
举个例子:
平时我们乘坐公车上班,公交车靠站,乘客上车(触发事件),那么公车就会在10秒之后出发(执行回调), 如果中途又有乘客上车(触发事件),那么又得重新等待10秒才会出发(重新计时)
使用场景的话,想象一下如果你要做一个 搜索 推荐,会根据用户输入的字符向后端拉取一个推荐列表,这种场景一般都是监听 input 的 keyup 事件, 用户不停的输入则不停的请求,将会造成大量的资源浪费,这时候我们就可以进行对用户输入的回调函数进行防抖包装,比如使其 一秒间隔停顿则向服务器请求数据这样子。
代码实现
const debounce = (fn, ms = 0) { let timer = null; return function(...args) { clearTimeout(timer); // 每次直接清除定时器 timer = setTimeout(() => { fn.apply(this, args) }, ms) } }
设定一个时间周期,在这个时间周期内不停的触发也只会执行一次
举个例子
假如地铁每间隔 3 分钟一班,这时候不能让地铁不发动去等待后面的乘客上车,因为时间都是预算好的,不能造成延误
函数节流会使用在比 input keyup 更频繁触发的事件中,比如 resize touchmove mousemove, scroll。 throttle 会强制的让函数以固定速率执行,因此这个方法比较适合应用于动画相关的场景。
throttle
const throttle = (fn, wait = 0) => { let timer, lastTime, callNow; return function(...args) { const context = this; // 第一次执行 if (!callNow) { fn.apply(context, args) lastTime = Date.now(); callNow = true; } else { // 否则每次都取当前时间跟最后执行时间的差 和 设定的时间间隔 作为比较 // 大于等于时间间隔则执行 clearTimeout(timer) timer = setTimeout(() => { if (Date.now() - lastTime >= wait) { fn.apply(context, args); lastTime = Date.now() } }, Math.max(wait - Date.now() - lastTime, 0)) } } }
如果文字体会的不是很理解,可以在(页面)[http://demo.nimius.net/debounce_throttle/]中看一下可视化的比较
参考链接: https://zhuanlan.zhihu.com/p/38313717
今天来梳理一下 JavaScript 中 防抖与节流
它们 两者 的目的都是为了 限制 某些事件监听的回调过于频繁的触发而进行的优化
比如:
防抖
概念
举个例子:
使用场景的话,想象一下如果你要做一个 搜索 推荐,会根据用户输入的字符向后端拉取一个推荐列表,这种场景一般都是监听 input 的 keyup 事件, 用户不停的输入则不停的请求,将会造成大量的资源浪费,这时候我们就可以进行对用户输入的回调函数进行防抖包装,比如使其 一秒间隔停顿则向服务器请求数据这样子。
代码实现
节流
概念
举个例子
函数节流会使用在比 input keyup 更频繁触发的事件中,比如 resize touchmove mousemove, scroll。
throttle
会强制的让函数以固定速率执行,因此这个方法比较适合应用于动画相关的场景。代码实现
如果文字体会的不是很理解,可以在(页面)[http://demo.nimius.net/debounce_throttle/]中看一下可视化的比较
参考链接: https://zhuanlan.zhihu.com/p/38313717