来源:http://blog.coding.net/blog/the-difference-between-throttle-and-debounce-in-underscorejs

Unserscore.js文档:http://www.bootcss.com/p/underscore/

github:https://github.com/jashkenas/underscore

在这里只讲了Unserscore.js其中的2个函数debounce throttle

debounce throttle使用场景

只要牵涉到连续事件或频率控制相关的应用都可以考虑到这两个函数,比如:

  • 游戏射击,keydown 事件
  • 文本输入、自动完成,keyup 事件
  • 鼠标移动,mousemove 事件
  • DOM 元素动态定位,window 对象的 resize 和 scroll 事件

前两者 debounce 和 throttle 都可以按需使用;后两者肯定是用 throttle 了。如果不做过滤处理,每秒种甚至会触发数十次相应的事件。尤其是 mousemove 事件,每移动一像素都可能触发一次事件。如果是在一个画布上做一个鼠标相关的应用,过滤事件处理是必须的,否则肯定会造成糟糕的体验。

Underscore.js是一个很精干的库,压缩后只有5.2KB。它提供了几十种函数式编程的方法,弥补了标准库的不足,大大方便了JavaScript的编程。

本文仅探讨Underscore.js的两个函数方法 _.throttle_.debounce 的原理、效果和用途。

通常的函数(或方法)调用过程分为三个部分:请求、执行和响应。(文中“请求”与“调用”同义,“响应”与“返回”同义,为了更好的表述,刻意采用请求和响应的说法。)

某些场景下,比如响应鼠标移动或者窗口大小调整的事件,触发频率比较高。若稍处理函数微复杂,需要较多的运算执行时间,响应速度跟不上触发频率,往往会出现延迟,导致假死或者卡顿感。

在运算资源不够的时候,最直观的解决办法就是升级硬件,诚然通过购买更好的硬件可以解决部分问题,但是也需要为此付出高额的成本。特别是客户端和服务器模式,要求客户端统一升级硬件基本不可能。

在资源有限的前提下,处理函数无法即时响应高频调用。退而求其次,只响应部分请求是否可行呢?某些场景下的密集性请求,具备很强的同质和连续性。比如说,鼠标移动的轨迹参数。响应越及时效果越平滑,但是如果响应速度跟不上时,反而会出现卡顿感,如果适当的丢弃一些请求效果更流畅。

throttledebounce 是解决请求和响应速度不匹配问题的两个方案。二者的差异在于选择不同的策略。

电梯超时

想象每天上班大厦底下的电梯。把电梯完成一次运送,类比为一次函数的执行和响应。假设电梯有两种运行策略 throttledebounce ,超时设定为15秒,不考虑容量限制。

  • throttle 策略的电梯。保证如果电梯第一个人进来后,15秒后准时运送一次,不等待。如果没有人,则待机。
  • debounce 策略的电梯。如果电梯里有人进来,等待15秒。如果又人进来,15秒等待重新计时,直到15秒超时,开始运送。

使用示例

_.throttle 使用示例

function log( event ) {
console.log( $(window).scrollTop(), event.timeStamp );
}; // 控制台记录窗口滚动事件,触发频率比你想象的要快
$(window).scroll( log ); // 控制台记录窗口滚动事件,每250ms最多触发一次
$(window).scroll( _.throttle( log, 250 ) );

_.debounce 使用示例

function ajax_lookup( event ) {
// 对输入的内容$(this).val()执行 Ajax 查询
}; // 字符输入的频率比你预想的要快,Ajax 请求来不及回复。
$('input:text').keyup( ajax_lookup ); // 当用户停顿250毫秒以后才开始查找
$('input:text').keyup( _.debounce( ajax_lookup, 250 ) );

可视化演示

示例中每一行都以30ms的速度绘制时间轴,第一行Mousemove Events是参考基准,以50ms每次的响应频率,在时间轴上输出循环可见ASCII码字符。

当鼠标进入左侧方型区域(mouseenter 事件)所有行开始绘制时间轴, 鼠标晃动(mousemove 事件)会在时间轴上绘制字符块,每个字符块表示事件被触发一次。为了展现延迟触发效果,相邻字符块的演示和文字是不同的。

顶部的两个按钮每100毫秒触发1次每200毫秒触发2次演示以固定频率匀速触发事件的效果。

浅谈 Unserscore.js 中 _.throttle 和 _.debounce 的差异的更多相关文章

  1. 浅谈 Underscore.js 中 _.throttle 和 _.debounce 的差异

    Underscore.js是一个很精干的库,压缩后只有5.2KB.它提供了几十种函数式编程的方法,弥补了标准库的不足,大大方便了JavaScript的编程. 本文仅探讨Underscore.js的两个 ...

  2. 【第三周读书笔记】浅谈node.js中的异步回调和用js-xlsx操作Excel表格

    在初步学习了node.js之后,我发现他的时序问题我一直都很模糊不清,所以我专门学习了一下这一块. 首先我们来形象地理解一下进程和线程: 进程:CPU执行任务的模块.线程:模块中的最小单元. 例如:c ...

  3. 浅谈 Underscore.js 中 _.throttle 和 _.debounce 的差异[转]

    看的文章来自: https://blog.coding.net/blog/the-difference-between-throttle-and-debounce-in-underscorejs 使用 ...

  4. 浅谈Vue.js

    作为一名Vue.js的忠实用户,我想有必要写点文章来歌颂这一门美好的语言了,我给它的总体评价是“简单却不失优雅,小巧而不乏大匠”,下面将围绕这句话给大家介绍Vue.js,希望能够激发你对Vue.js的 ...

  5. 浅谈C++11中的多线程(三)

    摘要 本篇文章围绕以下几个问题展开: 进程和线程的区别 何为并发?C++中如何解决并发问题?C++中多线程的基本操作 浅谈C++11中的多线程(一) - 唯有自己强大 - 博客园 (cnblogs.c ...

  6. 浅谈C++11中的多线程(二)

    摘要 本篇文章围绕以下几个问题展开: 进程和线程的区别 何为并发?C++中如何解决并发问题?C++中多线程的基本操作 浅谈C++11中的多线程(一) - 唯有自己强大 - 博客园 (cnblogs.c ...

  7. 转: 浅谈C/C++中的指针和数组(二)

    转自:http://www.cnblogs.com/dolphin0520/archive/2011/11/09/2242419.html 浅谈C/C++中的指针和数组(二) 前面已经讨论了指针和数组 ...

  8. 转:浅谈C/C++中的指针和数组(一)

    再次读的时候实践了一下代码,结果和原文不一致 error C2372: 'p' : redefinition; different types of indirection 不同类型的间接寻址 /// ...

  9. 转载 浅谈C/C++中的static和extern关键字

    浅谈C/C++中的static和extern关键字 2011-04-21 16:57 海子 博客园 字号:T | T   static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.ext ...

随机推荐

  1. poj 2031

    #include<stdio.h> #include<math.h> #include<stdlib.h> #define N 200 double co(doub ...

  2. RSA 数据加密和数字签名算法

    PKCS8EncodedKeySpec pkcs8KeySpec = KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Pr ...

  3. OpenCV使用GPU

    在使用OpenCV2.4.x的时候,以为不用重新编译可以直接使用GPU模块,不过在我使用的时候,发现使用getCudaEnabledDeviceCount()的时候,总是获得是0,于是重新编译Open ...

  4. WinCE:在Win7上连接WinCE手持设备

    当我们通过usb将WinCE 手持设备与Win7 PC连接后,我们通常希望通过Windows Mobile Center软件与手持设备实现同步.方法很简单,从下列列表中选择适合自己操作系统的Windo ...

  5. HDU 4363

    这题是记忆化搜索很容易想到,但状态却不好设 dp[i][j][u][d][l][r][k].对于矩形为i*j,它的四周的颜色分别为u,d,l,r,横竖切的状态为k的种数. 其中要注意一个问题是,停止不 ...

  6. HDU 4540

    简单得不能再简单的DP了. #include<iostream> const int inf=1<<30; using namespace std; int map[22][2 ...

  7. 虚拟化(四):vsphere高可用功能前提-共享存储搭建

    虚拟化(一):虚拟化及vmware产品介绍 虚拟化(二):虚拟化及vmware workstation产品使用 虚拟化(三):vsphere套件的安装注意及使用 虚拟化(四):vsphere高可用功能 ...

  8. java面向接口编程

    在oop中有一种设计原则是面向接口编程,面向接口编程有非常多优点,详细百度一大片.我来谈一下详细的使用中的一些不成熟的见解.! 首先面向接口编程能够消除类之间的依赖关系,使得业务仅仅依赖接口. 这样有 ...

  9. java wait 与 notify sleep

    来自:http://blog.csdn.net/zyplus/article/details/6672775 有适当的代码修改. 在JAVA中,是没有类似于PV操作.进程互斥等相关的方法的.JAVA的 ...

  10. android app记录执行日志 捕获奔溃异常 ,存储日志到文件

    app在执行过程中.为了后期的维护升级,记录日志是一个很好的方法. 为了读取到app执行时的日志,一般的作法是单独开一个线程,在app执行的启动线程.然后app退出时停掉线程. 然而我们更好的方法是开 ...