[转]Javascript函数节流与函数去抖

作者: haibao 分类: 其他 发布时间: 2017-10-11 10:08
以铜为镜, 可以正衣冠; 以史为镜, 可以知兴替; 以人为镜, 可以明得失。——李世民 (唐太宗)

介绍

首先解释一下这两个概念:

函数节流(throttle):是让一个函数无法在很短的时间间隔内连续调用,当上一次函数执行后过了规定的时间间隔,才能进行下一次该函数的调用。

函数去抖(debounce):让一个函数在一定间隔内没有被调用时,才开始执行被调用方法。

两个方法都是用来提升前端性能,减轻浏览器压力。

应用

理解起来有点费力,通过应用来理解就轻松了。通常,我们会在有用户交互参与的地方添加事件,而往往这种事件会被频繁触发。

想象一下窗口的resize事件或者是一个元素的onmousemove事件,resize会在改变浏览器大小事连续触发、onmousemove会在鼠标移动时被连续触发,如果你的回调过重,你可能使浏览器死掉。

想象一下你需要在用户输入一段文字时对文字进行处理,你监听文字改变,每一次改变都会调用一次回调函数,其实我需要的是在用户输入停下来的时候去处理一次。

射击游戏中你希望1s中之内只能发射一颗子弹,而不是用户每按一次发射就发射。

类似的应用还有很多,throttle和debounce的区别就是在频繁的回调中,throttle以一定频率运行,而debounce在频繁回调之后运行。总的来说就是过滤频繁触发的事件回调,使其在真正需要的时候执行,两者根据应用场景自行选择。

实现

说了这么多,怎么使用debounce和throttle功能呢,伟大的 http://underscorejs.org 给我们实现好了这两个方法,这两个方法的实现都是不依赖于其他underscore方法的,所以我们可以轻易的添加到其他JavaScript库中,比如jQuery

debounce

这里暂时不考虑immediate,有兴趣可以自己研究。

函数去抖的基本思想是:对需要去抖的函数做包装,使用闭包记录timeout,第一次回调给函数设置 setTimeout定时器,只要在wait时间内,后一次的回调会clearTimeout取消前一次回调的执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var debounce = function(func, wait, immediate) {
    var timeout, result;
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        if (!immediate) result = func.apply(context, args);
      };
      var callNow = immediate && !timeout;
      clearTimeout(timeout);
      timeout = setTimeout(later, wait);
      if (callNow) result = func.apply(context, args);
      return result;
    };
  };
 
// 举个栗子:
function query() { 
  //进行异步调用查询 
}
 
var lazyQuery = debounce(query, 300);
$('#search').keypress(lazyQuery);

throttle

函数节流的基本思想是:无视浏览器的回调,自己按一定频率执行代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
var throttle = function(func, wait) {
    var context, args, timeout, result;
    var previous = 0;
    var later = function() {
      previous = new Date;
      timeout = null;
      result = func.apply(context, args);
    };
    return function() {
      var now = new Date;
      var remaining = wait - (now - previous);
      context = this;
      args = arguments;
      if (remaining <= 0) {
        clearTimeout(timeout);
        timeout = null;
        previous = now;
        result = func.apply(context, args);
      } else if (!timeout) {
        timeout = setTimeout(later, remaining);
      }
      return result;
    };
  };
 
  //举个栗子:
  function handleScroll() {
        //进行异步调用查询
        var scrollTop = $(window).scrollTop();
        var scrollHeight = $(document).height();
        var windowHeight = $(window).height();
 
        if(scrollTop + windowHeight >= scrollHeight){
            if(!flag){
                moocs.getListParams.page++;
                moocs.getMoocList();
            }
        }
    }
 
    var throttled = throttle(handleScroll, 300);
    $(window).scroll(throttled);

应用场景:

函数节流(throttle)

1. 频繁的mousemove/keydown,比如高频的鼠标移动,游戏射击类的

2. 搜索联想(keyup

3. 进度条(我们可能不需要高频的更新进度)

4. 拖拽的dragover

5. 高频的点击,抽奖等(哈哈,邪恶)

函数防抖(debounce)

1. scroll/resize事件

2. 文本连续输入,ajax验证/关键字搜索

参考资料:

1.JavaScript高级程序设计
2.http://www.cnblogs.com/ambar/archive/2011/10/08/throttle-and-debounce.html

注:本文转自:http://blog.csdn.net/dyllove98/article/details/9281507

本文地址:[[转]Javascript函数节流与函数去抖],如没有标注转载,均为原创,转载请保留出处和链接,欢迎分享 谢谢。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>