在项目中,我们有时候做需求的时候会与后端做一些交互,需要去频繁的调取接口,比如模糊查询的下拉列表,是否勾选邮件订阅,如果使用change事件去异步查询接口,可能会在短时间频繁调取接口,同时操作人数过多极容易给后端服务器照成极大的压力。(本来这事是不屑于做的,但是隔壁项目组经常甩锅给我们,说我们code影响他们性能[手动滑稽])这时候我们就应该从前端做些优化操作了,前端防抖和节流就产生了。
- 防抖:就是在用户连续操作停止之后的一段时间会触发一次事件,不会频繁请求接口,需求如下图例子所示:

这里是一个邮件订阅功能,用户在前端不管连续怎么点击,都会一最后一次点击事件状态为准,然后请求后端接口,关于这个连续定义的停顿事件是可以设定的.有了需求我们来看看代码方面的实现,下面我们是使用jQuery实现,代码如下:
function emailNotice(type){ // 订阅请求
var url = window.location.href + '.../' + type
$.ajax({
url:url,
data: {},
type: "GET",
success: function (res) {
// to do ...
},
error: function (err) {
// to do ...
}
});
}
// 防抖函数处理邮件订阅,以最后一次改变为准
function debounce(fn, wait) {
var timeout = null
$('.gift-link-sub').on('click', function () { // 给DOM添加勾选和未选择的样式
if ($(this).hasClass('gift-link-sub-noactive')) {
$(this).removeClass('gift-link-sub-noactive')
} else {
$(this).addClass('gift-link-sub-noactive')
}
})
return function() {
if(timeout !== null)
clearTimeout(timeout)
timeout = setTimeout(fn, wait)
}
}
// 回调函数
function handle() {
if ($('.gift-link-sub').hasClass('gift-link-sub-noactive')) {
emailNotice(0); // 未选中回调取消订阅的接口
} else {
emailNotice(1); // 选中回调订阅的接口
}
}
$('.gift-link-sub').on('click', debounce(handle, 1000)); // 给DOM元素绑定点击事件,定义停顿1s之后触发事件
经过上述函数处理之后的操作,用户在连续点击停止之后1s后会执行一次订阅/取消订阅邮件的接口,极大的减轻服务器压力。(停顿时间小于一秒不认为是停顿,认为是连续操作[滑稽])
2.节流: 节流就是在同一时间段内,事件只会触发一次,比如,我们把用户的连续点击看作是一个持续的事件,在0-100ms分为一个时间段,100-200ms为第二个时间段,200-300ms为第三个时间段。假如用户在这个300ms的时间段里总共点击了10次,但是我们只请求了三次,第一个时间段请求一次,第二次时间段请求一次,第三次时间段请求请求一次,节省了7次的请求压力。
例如:上图我们有个搜索操作,下拉列表会模糊匹配热词或者用户可能点击进行搜索的关键词,假如我们使用input的默认change事件去请求接口的话,会造成服务器极大的浪费,而且在网络不稳定的情况下吗,多次请求,造成请求队列中,返回信息错乱的问题。比如我先发送的请求,却在网络延迟之后,后返回的结果,前端拿到结果之后,马上渲染到页面上,导致输入和搜索返回结果不一致的bug。那么下面我们就可以使用节流函数去处理我们的查询你操作。代码如下图所示:
function searchKeyWord(word){ // 搜索请求
var url = window.location.href + '.../'
$.ajax({
url:url,
data: {key_word: word},
type: "GET",
success: function (res) {
// to do ...
},
error: function (err) {
// to do ...
}
});
}
// 节流处理函数,每段时间内只会执行一次
function throttle(fn, wait) {
var last, deferTimer
return function (args) {
var that = this
var _args = arguments
var now = + new Date()
if (last && now < last + wait) { // 时间戳对比
clearTimeout(deferTimer)
deferTimer = setTimeout(function () {
last = now
fn.apply(that, _args)
}, wait)
}else {
last = now
fn.apply(that,_args)
}
}
}
// 回调函数
function handle() {
searchKeyWord ('value')
}
$('.search').on('change', throttle(handle, 100)); // 给DOM元素绑定事件,每.1s内触发事件一次
我们在上述处理之后,每隔100ms会响应一次事件,在同一时间段内,不管点击多少次只会执行一次。
防抖和节流的总结如下图所示:

5399

被折叠的 条评论
为什么被折叠?



