2019-07-16 JS(debounce 、throttle、requestAnimationFrame)

参考:http://www.cnblogs.com/wilber2013/
https://segmentfault.com/a/1190000004909376

通常有这些场景会需要优化性能:
1、鼠标事件:mousemove(拖曳)/mouseover(划过)/mouseWheel(滚屏)
2、键盘事件:keypress(基于ajax的用户名唯一性校验)/keyup(文本输入检验、自动完成)/keydown(游戏中的射击)
3、window的resize/scroll事件(DOM元素动态定位)

throttle(节流)与debounce(防抖)是两个类似的概念,目的都是随着时间的推移控制执行函数的次数,但是有些细微的差别。

当我们为DOM事件关联方法时,若我们有一个debounced和throttled函数将会很方便,为何?因为这样我们可以在事件和执行函数之间添加一层控制,注意我们并没有去控制DOM事件触发的次数。

export function debounce(method, wait, immediate) {
let timeout;
let result;
let debounced = function(...args) {
return new Promise(resolve => {
let context = this;
if (timeout) {
clearTimeout(timeout);
}
if (immediate) {
let callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait);
if (callNow) {
result = method.apply(context, args);
resolve(result);
}
} else {
timeout = setTimeout(() => {
result = method.apply(context, args);
resolve(result);
}, wait);
}
});
};

debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
};

return debounced;
}

1、Debounce技术使我们可以将一个连续的调用归为一个。
Lodash在.debounce和.throttle中添加了许多特性。immediate标示替代了leading和trailing。你可以二选一或者都选,默认情况下,只有trailing是开启的。

debounce的作用是,当调用动作触发一段时间后,才会执行该动作,若在这段时间间隔内又调用此动作则将重新计算时间间隔。

throttle的作用是,预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新的时间周期。

2、throttle跟debounce的最大不同就是,throttle会有一个阀值,当到达阀值的时候action必定会执行一次。

所以throttle的实现可以基于前面的debounce的实现,只需要加上一个阀值。

3、requestAnimationFrame:可替代 throttle ,函数需要重新计算和渲染屏幕上的元素时,想保证动画或变化的平滑性,可以用它。注意:IE9 不支持。

4、常用场景:
debounce:
对于键盘事件,当用户输入比较频繁的时候,可以通过debounce合并键盘事件处理
对于ajax请求的情况,例如当页面下拉超过一定返回就通过ajax请求新的页面内容,这时候可以通过debounce合并ajax请求事件

throttle:
对于键盘事件,当用户输入非常频繁,但是我们又必须要在一定时间内(阀值)内执行处理函数的时候,就可以使用throttle

例如,一些网页游戏的键盘事件
对于鼠标移动和窗口滚动,鼠标的移动和窗口的滚动会带来大量的事件,但是在一段时间内又必须看到页面的效果

例如对于可以拖动的div,如果使用debounce,那么div会在拖动停止后一下子跳到目标位置;这时就需要使用throttle

你可能感兴趣的:(2019-07-16 JS(debounce 、throttle、requestAnimationFrame))