函数节流和防抖

一、函数节流

所谓节流,就是控制某个函数在某一时间内,只能执行一次。应用场景一般是在拉动滚动条进行懒加载,为了防止过度请求,所以加上节流控制,防止服务器过载。

知道其原理之后,我们就可以思考一下如何进行节流。“某一时间内只能执行一次该函数”,那么我们自然而然就会想到一个函数,setTimeout()。那我们来尝试一下:

 1 function throttle(func, wait) {
 2     // 利用闭包,保存计时器timeout
 3     let timeout;
 4     return function() {
 5         let context = this;  // 此处的this指向的是window
 6         let args = arguments;
 7         // 如果计时器已经结束,那么就可以执行func函数了
 8         if (!timeout) {
 9             timeout = setTimeout(() => {
10                 timeout = null;
11                 func.apply(context, args)
12             }, wait)
13         }
14     }
15 }

但也有另外一种方法,用时间戳来控制是否执行func。

 1 function throttle(func, wait) {
 2     // 上一次执行的时间
 3     let previous = 0;
 4     return function() {
 5         // 当前时间
 6         let now = Date.now();
 7         let context = this;
 8         let args = arguments;
 9         // 若当前时间与上一次执行func的时间差超过了wait,那么就可以执行func了,并且将prev置为now
10         if (now - previous > wait) {
11             func.apply(context, args);
12             previous = now;
13         }
14     }
15 }

二、函数防抖

函数防抖与函数节流差不多,但是也有其差距。比如说,我想要让func在3秒内只能执行一次,如果使用了节流,那么在我执行完func的3秒内,无论我怎么操作都不会影响下一次执行的时间。但是如果我用了防抖,在我执行了func函数的3秒内,如果我再次执行func,那么内部的定时器将会重置,我需要再等3秒后才能执行func。

我们先看代码

 1 /**
 2  * @desc 函数防抖
 3  * @param func 函数
 4  * @param wait 延迟执行毫秒数
 5  * @param immediate true 表立即执行,false 表非立即执行
 6  */
 7 function debounce(func,wait,immediate) {
 8     let timeout;
 9 
10     return function () {
11         let context = this;
12         let args = arguments;
13 
14         if (timeout) clearTimeout(timeout);
15         if (immediate) {
16             var callNow = !timeout;
17             timeout = setTimeout(() => {
18                 timeout = null;
19             }, wait)
20             if (callNow) func.apply(context, args)
21         }
22         else {
23             timeout = setTimeout(function(){
24                 func.apply(context, args)
25             }, wait);
26         }
27     }
28 }

我们先设置一个定时器,在需要调用函数的时候,如果发现定时器还处于计时状态,那么就将其清空(第14行),再重新进行计时。参数immediate是控制是否立刻执行func,这个可根据实际应用场景进行选择(可参考https://www.jianshu.com/p/c8b86b09daf0)。

三、总结

在进行窗口的resize、scroll,输入框内容校验等操作时,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕。此时我们可以采用debounce(防抖)和throttle(节流)的方式来减少调用频率,同时又不影响实际效果。 

posted @ 2019-10-22 11:24  卑微小陈的随笔  阅读(183)  评论(0编辑  收藏  举报