何为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. [原]Python 简单异常处理

    s=raw_input("Input your age:") if s =="": raise Exception("Input must no be ...

  2. 取得Android平台某设备上所有可用的Sensors

    本来要写一个检测手机的温度的小应用,学习一下传感器的api,可结果怎么写不行.经检测,发现取得的Sensor为NULL,这才明白,我手机没有TYPE_AMBIENT_TEMPERATURE传感器. 于 ...

  3. oracle 数组类型

    create or replace function my_test(p_str varchar2) return number as --普通变量 v_var ); --固定长度数组 type v_ ...

  4. Change Homepage Logo

     Open the following defination and changed them. 1. NEW_PS_LOGO (Image Type) - To change the logo.2. ...

  5. C#winform在textbox插入内容换行

    要让一个TextBox显示多行文本就得把它的Multiline属性设置为true,可是如果你是要把TextBox的Text属性设置多行文本时可能会遇到点麻烦,也许你会想到直接加一个换行符"\ ...

  6. [leetcode]_Palindrome Number

    判断integer是否为回文串(负数全部不为回文串) 思路很直接,提取出integer中的每一位,一头一尾进行比较是否相同. 一次AC , 直接上代码: public boolean isPalind ...

  7. hbase与Hadoop

    Hbase是一种低延迟的在线系统,Hadoop是优化吞吐量的离线系统.这种互补关系造就了一种强大的.灵活的数据平台,可以用来搭建水平扩展的数据应用.

  8. Like ruby of SBM Crusher zip to dict

    how to use the zip to bulid a dict in python? data = """A dynamic, interpreted, open ...

  9. js 将json字符串转换为json兑现

    在数据传输过程中,json是以文本,即字符串的形式传递的,而JS操作的是JSON对象,所以,JSON对象和JSON字符串之间的相互转换是关键.例如:JSON字符串:var str1 = '{ &quo ...

  10. jQuery基础知识--选择器与效果

    $(this).hide()-----隐藏当前元素 $("p").hide()------隐藏所有段落 $(".test").hide()--隐藏所有class ...