小程序开发完成,闲来无事想要优化一下,就想到了这个函数节流和函数防抖。这两个内容也算是老生常谈的问题了,函数的节流和防抖是优化高频率执行js代码的一种手段,js中的一些事件在执行触发时,会不断调用 绑定在事件上的回调函数,极大的浪费资源,降低性能。为了优化体验,需要对这类事件进行调用次数的限制,此时引入函数节流防抖。
函数节流(throttle)
含义:
控制事件发生的频率。单位时间 n 秒内,第一次触发函数并执行,以后 n 秒内不管触发多少次,都不执行,直到下一个单位时间 n 秒。
应用场景:
- 比如
scroll
事件,滚动监听事件,每隔一段时间计算一次位置信息等; - 浏览器的播放事件,每隔1s计算一次进度信息;
input
框实时搜索并发送请求展示下拉列表,每隔1s发送一次请求。(防抖也可以);- 高频点击提交,表单重复提交。
函数防抖(debounce)
含义:
防止抖动,延迟函数执行,以免把一次事件误执行多次,影响性能。 不管该函数触发了多少次,只在最后一次触发该函数时,才定义 setTimeout
,到达间隔时间再执行 需要防抖的函数。
应用场景:
- 登录注册、发短信等按钮避免用户点击过快,导致多次发送请求,需要防抖;
- 调整浏览器窗口大小时,
resize
次数过于频繁,造成计算过多,此时需要一次到位,需要防抖; - 文本编辑器实时保存,无任何更改操作一段时间后自动保存;
mousemove
、mouseover
鼠标移动事件防抖;input
搜索输入框搜索输入,只需要用户最后一次输入完,再发送请求防抖;- 手机号、邮箱验证输入检测等。
在小程序中的使用
一般将这两个方法封装到一个公用的 tools.js
工具类中。
// tools.js
/* 函数节流 */
function throttle(fn, interval) {
let timer; // 维护一个 timer
let delay = interval|| 500; // 设置间隔时间,如果interval不传,则默认500ms
return function () {
let _this = this;
let args = arguments;
if (timer) {
return;
}
timer = setTimeout(function () {
fn.apply(_this, args);
timer = null;
// 在interval后执行完fn之后清空timer,此时timer为假,throttle触发可以进入计时器
}, delay)
}
}
/* 函数防抖 */
function debounce(fn, interval) {
let timer; // 维护一个 timer
let delay = interval || 1000; // 间隔时间,如果interval不传,则默认1000ms
return function () {
let that = this;
let args = arguments; // 保存此处的arguments,因为setTimeout是全局的,arguments不是防抖函数需要的。
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
fn.apply(that, args); // 用apply指向调用debounce的对象,相当于this.fn(args);
}, delay);
};
}
module.exports = {
throttle: throttle,
debounce: debounce
}
在需要使用的地方引入调用即可。
let tools = require('../../utils/tools')
Page({
data: { },
// 使用throttle函数
onThrottle: tools.throttle(function(){
// 函数执行
console.log("throttle函数")
} , 300),
// 使用debounce函数
onDebounce: tools.debounce(function(){
// 函数执行
console.log("debounce函数")
} , 1200),
// 正常函数执行
onFun: function(){
console.log("正常函数执行")
}
})
比较
相同点:
- 都可以通过使用
setTimeout
实现; - 目的都是为了降低回调执行频率,节省计算资源。
不同点:
- 函数防抖:在一段连续操作结束后,处理回调,利用
clearTimeout
和setTimeout
实现。 - 函数节流:在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用它来提高性能。
- 函数防抖关注一定时间连续触发的事件只在最后执行一次,而函数节流侧重于一段时间内只执行一次。
总结
防抖:防止抖动,单位时间内事件触发会被重置,避免事件被误伤触发多次。代码实现重在清零 clearTimeout
。防抖可以比作等电梯,只要有人进来,就需要再等一会。业务场景有避免触发按钮多次重复提交。
节流:控制流量,单位时间内事件只能触发一次。代码实现重在开锁关锁 timer = timeout;
timer = null;
。节流可以比作红绿灯,每等一个红灯时间就可以过一批。
这两个优化函数在平时还是会经常用到的,大家有什么问题欢迎评论区留言讨论,欢迎大家点赞转发,大家共同进步。