一、节流
什么是节流?
就像春节回家过安检一样,你会发现有个保安人员拦住你,等到安检机前没人的时候再让你进。
一个函数频繁地被调用可能导致异常情况,所以要让它隔段时间再执行。
为什么要节流?
这样做可以避免因人流太大导致安检机一次要处理的行李过多,人员拥挤等状况。
js中的节流可以避免资源浪费,异常情况的发生等。
_.throttle
var throttled = _.throttle(updatePosition, 100);
$(window).scroll(throttled);
创建并返回一个像节流阀一样的函数,当重复调用函数的时候,至少每隔 wait毫秒调用一次该函数。对于想控制一些触发频率较高的事件有帮助。
_.throttle = function(func, wait, options) {
var timeout, context, args, result
var previous = 0
if (!options) options = {}
var later = function() {
previous = options.leading === false ? 0 : _.now()
timeout = null
result = func.apply(context, args)
if (!timeout) context = args = null
}
var throttled = function() {
var now = _.now()
if (!previous && options.leading === false) previous = now
var remaining = wait - (now - previous)
context = this
args = arguments
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout)
timeout = null
}
previous = now
result = func.apply(context, args)
if (!timeout) context = args = null
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining)
}
return result
}
throttled.cancel = function() {
clearTimeout(timeout)
previous = 0
timeout = context = args = null
}
return throttled
}
函数 | 作用 |
---|---|
now | 获取当前的时间戳 |
clearTimeout | 取消延时器 |
讲解
throttle内部定义了三个方法
- later:下一次的执行
- throttled:定义本次执行立即执行还是等待执行
- cancel:取消延时的执行队列
核心的实现逻辑表述为:
每次执行时根据上一次的执行时间快照判断这次的执行是否wait间隔内,如果是则延时剩余时间调用,否则,立即执行 并将等待的延时器清空。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxCd0JjYwB3VhVHdywEMW1mY1RzRapnTtxkb5ckYplTeMZTTINGMShUYfRHelRHLwEzX39GZhh2css2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xyayFWbyVGdhd3LcV2Zh1Wa9M3clN2byBXLzN3btg3Pn5GcuIDOzUTOzYTM0EDMxkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
二、防抖
什么是防抖?
实时搜索中,输入框每输入一个字符就查询一次,因为输入结果的不确定性就很容易造成“性能爆炸”,且会给用户造成困扰。
在事件被触发n秒后,再去执行回调函数。如果n秒内该事件被重新触发,则重新计时。结果就是将频繁触发的事件合并为一次,且在最后执行。
为什么要防抖?
js中的防抖可以避免“性能爆炸”,异常情况的发生等。
_.debounce
var lazyLayout = _.debounce(calculateLayout, 300);
$(window).resize(lazyLayout);
返回 function 函数的防反跳版本, 将延迟函数的执行(真正的执行)在函数最后一次调用时刻的 wait 毫秒之后. 对于必须在一些输入(多是一些用户操作)停止到达之后执行的行为有帮助。 例如: 渲染一个Markdown格式的评论预览, 当窗口停止改变大小之后重新计算布局, 等等.
_.debounce = function(func, wait, immediate) {
var timeout, result
var later = function(context, args) {
timeout = null
if (args) result = func.apply(context, args)
}
var debounced = restArguments(function(args) {
if (timeout) clearTimeout(timeout)
if (immediate) {
var callNow = !timeout
timeout = setTimeout(later, wait)
if (callNow) result = func.apply(this, args)
} else {
timeout = _.delay(later, wait, this, args)
}
return result
})
debounced.cancel = function() {
clearTimeout(timeout)
timeout = null
}
return debounced
}
函数 | 作用 |
---|---|
delay | 延时执行器 |
讲解
debounced内部定义了三个方法
- later:下一次的执行
- debounced:主函数
- cancel:取消延时的执行队列