何为throttle, 何为debounce?

谷歌翻译给出的意思:throttle 掐死???   debounce 去抖

好吧,按理解我们习惯翻译成 ——节流。

那么在什么场景下需要用到?

场景一:onresize,onscroll,onmousemove

场景二:input,autocomplete

如果我们什么都不做,浏览器将会频繁的调用你绑定的事件,如果电脑配置低就会感觉卡滞,也就是你的应用性能太差。

入门级写法:——拖动就fire注册的事件

function onResize(){
    console.log('log');
};
window.addEventListener('resize',onResize,false)

进阶级写法:——等你安静了我再调用

var timer = null;
function onResize(){
clearTimeout(timer);
timer = setTimeout(function(){
console.log('log');
},200);
};
window.addEventListener('resize',onResize,false)

这里有个问题:引入了变量timer,它其实属于onResize的,但是你不能放到onResie里面。这样写实在是太丑了,得想办法。

如果我们把这个变量注册为onResize的属性,变成:

function onResize(){
clearTimeout(onResize.timer); //this is difference
onResize.timer = setTimeout(function(){
console.log('log');
},200);
};
window.addEventListener('resize',onResize,false)

插句:这种方法在proxy中用处比较大。大家都知道要移除注册给dom的事件,需要指向一致,这个proxy就可以派上用场了。i.e,仅仅是个栗子!

Contextmenu.prototype = {
proxy: function(fn){
if(!fn._contextmenu_proxy){
fn._contextmenu_proxy = $.proxy(fn, this);
}
return fn._contextmenu_proxy;
},
init:function(dialModel,dialView){
var me = this;
$document.on('contextmenu',me.proxy(me.onContextMenu));
}
}

再进阶级写法:——封装

网上漫天叫嚣着“面向对象,封装,继承……” 你要不封装一个,还面向过程 是不是会喷死?

上面我们其实已经实现了基础的函数节流。但我们不能每次都要写同样的逻辑吧。所以抽象一个公用函数来做这件事,具体可以这样实现。

jquery是这样做的,google 能搜到$.throttle,但是为啥我在源码里没搜到???

underscore.js是这样实现的:

_.throttle = function(func, wait, options) {
var context, args, result;
var timeout = null;
var previous = 0;
options || (options = {});
var later = function() {
previous = options.leading === false ? 0 : new Date;
timeout = null;
result = func.apply(context, args);
};
return function() {
var now = new Date;
if (!previous && options.leading === false) previous = now;
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 && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
}; // Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout, args, context, timestamp, result;
return function() {
context = this;
args = arguments;
timestamp = new Date();
var later = function() {
var last = (new Date()) - timestamp;
if (last < wait) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) result = func.apply(context, args);
}
};
var callNow = immediate && !timeout;
if (!timeout) {
timeout = setTimeout(later, wait);
}
if (callNow) result = func.apply(context, args);
return result;
};
};

调用:

function updatePosition(){
//console.log('s');
};
//默认立即执行第一次,如果不想要立即执行,可以这样 _.throttle(updatePosition, 500,{leading:false});
//默认当你停止操作时会延时执行最后一次,如果不想要,可以这样   _.throttle(updatePosition, 500,{trailing:false});

var throttled = _.throttle(updatePosition, 500); 
$(window).scroll(throttled);

//debonce——debonce的意思,打个比方:你乘电梯经常碰到快要关门时有人要上,电梯得再次开了让人上来。这个过程可能反复好几次,如果我们一致等着,等到一个时间间隔没人时再关门,是不是方便很//多,不太形象,大概也能明白什么意思

function calculateLayout(){
   console.log('resize');
};

//如果想要立即执行,传入参数true  _.debounce(calculateLayout, 2000,true);
var lazyLayout = _.debounce(calculateLayout, 2000);
$(window).resize(lazyLayout);

baidu Tangram  

貌似没看到??

好吧,我们来实现一个简单的封装,不需要那么复杂,好理解的版本。

/*
*author@http://wuya1234.github.io
*思路: 1.之前已经说过,可以用setTimeout延时处理太频繁的操作 2.但是我们不想让操作过程一直没有反应,所以需要指定比如:每隔200毫秒不管怎样都执行一次
*/
function throttle(fn,delay,mustRun){
var timer,
t_start,
previous;
return function(){
var arg = arguments,
scope = this;
var now = +new Date;
var defer = function(){
previous = now;
fn.call(scope,arg);
}; var diff = now - previous - delay;
if(diff <= 0){
clearTimeout(timer);
timeout = timer;
previous = now;
fn.call(scope,arg);
}else{
timer = setTimeout(fn.call(scope,arg),diff);
}
};
}; function onResize(){
clearTimeout(onResize.timer);
onResize.timer = setTimeout(function(){
console.log('log');
},200);
};
window.addEventListener('resize',throttle(onResize),false);

更多相关知识可以到这些地方看看:

1.http://remysharp.com/2010/07/21/throttling-function-calls/

3.http://www.css88.com/archives/5256#more-5256

4.http://www.alloyteam.com/2012/11/javascript-throttle/

throttle/debounce: 为你的cpu减减压(前端性能优化)的更多相关文章

  1. 嵌入式 如何定位死循环或高CPU使用率(linux) 及性能优化

    嵌入式 如何定位死循环或高CPU使用率(linux) ln -s /mnt/nfs/_install/usr/bin/sort /usr/bin/sort awk '{print $1,$2,$14, ...

  2. paip.提升性能---mysql 优化cpu多核以及lan性能的关系.

    paip.提升性能---mysql 优化cpu多核以及lan性能的关系. 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http:/ ...

  3. [Unity优化] Unity CPU性能优化

    前段时间本人转战unity手游,由于作者(Chwen)之前参与端游开发,有些端游的经验可以直接移植到手游,比如项目框架架构.代码设计.部分性能分析,而对于移动终端而言,CPU.内存.显卡甚至电池等硬件 ...

  4. python GIL 全局锁,多核cpu下的多线程性能究竟如何?

    python GIL 全局锁,多核cpu下的多线程性能究竟如何?GIL全称Global Interpreter Lock GIL是什么? 首先需要明确的一点是GIL并不是Python的特性,它是在实现 ...

  5. Linux性能优化之CPU优化(一)

    前言 何为性能优化?个人认为,性能优化是为了提高应用程序或系统能力为目的.那么如何才能实现对应用程序的性能调优呢?这里很设计到很多的内容,包括Linux内核.CPU架构以及Linux内核对资源的分配以 ...

  6. 《Linux 性能优化实战—倪朋飞 》学习笔记 CPU 篇

    平均负载 指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,即平均活跃进程数 可运行状态:正在使用CPU或者正在等待CPU 的进程,也就是我们常用 ps 命令看到的,处于 R 状态 (Run ...

  7. 性能优化之基础资源cpu&内存(JVM)

    本章主要介绍计算机的一些基础资源以及操作系统处理后的一些基础资源. 主要包括 cpu 内存 磁盘 网络 线程 本章会介绍这些资源的一些原理,介绍如何查看资源的数量,使用情况,对性能和整体计算机执行的一 ...

  8. 鲲鹏性能优化十板斧(二)——CPU与内存子系统性能调优

    1.1 CPU与内存子系统性能调优简介 调优思路 性能优化的思路如下: l   如果CPU的利用率不高,说明资源没有充分利用,可以通过工具(如strace)查看应用程序阻塞在哪里,一般为磁盘,网络或应 ...

  9. 性能优化处理CPU快慢问题

    经常听到有人说磁盘很慢.网络很卡,这都是站在人类的感知维度去表述的,比如拷贝一个文件到硬盘需要几分钟到几十分钟,够我去吃个饭啦:而从网络下载一部电影,有时候需要几个小时,我都可以睡一觉了. 最为我们熟 ...

随机推荐

  1. Dev的DocumentManager添加窗体

    1.DocumentManager要设置自己的MdiParent属性 2.主窗体设置IsMidContainer为True 3.要生成的窗体设置MdiParent为主窗体 4.正常创建窗体,然后就可以 ...

  2. 配置NTP服务ntpd/ntp.conf(搭建Hadoop集群可参考)

    本文拟定是在一个局域网内(比如一个Hadoop集群)设定一台NTP服务器作为整个网络的标准时间参考,使用网络(集群)内的所有机器保持时间一致!以下是详细的操作步骤: 1. 修改选定的服务器的本地时间 ...

  3. cassandra 之 jdbc 使用【java、scala】

    1.数据库创建 参考接上文cassandra入门 http://www.cnblogs.com/piaolingzxh/p/4197833.html 2.下载jdbc驱动源码,构建jar包 源码下载地 ...

  4. MapReduce数据流

    图4.5细节化的Hadoop MapReduce数据流 图4.5展示了流线水中的更多机制.虽然只有2个节点,但相同的流水线可以复制到跨越大量节点的系统上.下去的几个段落会详细讲述MapReduce程序 ...

  5. Timer wheel etc.

    http://code.google.com/p/hierarchal-wheel-timer/ 最小堆的实现(C 语言版) 最小堆的实现(java) Linux 下定时器的实现方式分析 更快bobh ...

  6. Linux操作系统常用命令

    http://www.cnblogs.com/huangzelin/p/5617611.html http://www.cnblogs.com/liumt/p/6117168.html

  7. [下载] VS 2013 Update 4 & 社群版 (Visual Studio Community) & VS 2015 Preview预览版

    这是我的备份,原文请看http://www.dotblogs.com.tw/mis2000lab/archive/2014/11/13/vs2013_update4_community_vs2015_ ...

  8. 可以获取get post url 传递参数的统一方法

    public static string objRequest(string requestName) { object obj = HttpContext.Current.Request[reque ...

  9. Learning Scrapy笔记(一)- Scrapy简单介绍

    Scrapy简述 Scrapy十一个健壮的,用来从互联网上抓取数据的web框架,Scrapy只需要一个配置文件就能组合各种组件和配置选项,并且Scrapy是基于事件(event-based)的架构,使 ...

  10. Shell 内置操作符-字符串处理(汇总)

    一.判断读取字符串值 表达式 含义 ${var} 变量var的值, 与$var相同     ${var-DEFAULT} 如果var没有被声明, 那么就以$DEFAULT作为其值 * ${var:-D ...