函数节流的目的

从字面上就可以理解,函数节流就是用来节流函数从而一定程度上优化性能的。例如,DOM 操作比起非DOM 交互需要更多的内存和CPU时间。连续尝试进行过多的DOM 相关操作可能会导致浏览器挂起,有时候甚至会崩溃。尤其在IE 中使用onresize 事件处理程序的时候容易发生,当调整浏览器大小的时候,该事件会连续触发。在onresize 事件处理程序内部如果尝试进行DOM 操作,其高频率的更改可能会让浏览器崩溃。又例如,我们常见的一个搜索的功能,我们一般是绑定keyup事件,每按下一次键盘就搜索一次。但是我们的目的主要是每输入一些内容搜索一次而已。为了解决这些问题,就可以使用定时器对函数进行节流。

函数节流的原理

某些代码不可以在没有间断的情况连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。目的是只有在执行函数的请求停止了一段时间之后才执行。

函数节流的基本模式


JavaScript

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 var processor = {
   timeoutId: null,
     //实际进行处理的方法
   performProcessing: function(){
     //实际执行的代码
   },
  //初始处理调用的方法
  process: function(){
    clearTimeout(this.timeoutId);
    var that = this;
    this.timeoutId = setTimeout(function(){
      that.performProcessing();
    }, 100);
  }
};
//尝试开始执行
processor.process();

好吧,看得确实有点迷糊。下面通过一个例子来详细说明,并且在这个基础模式之上做一个优化处理。

例子场景:实现常见的搜索功能

①没有使用函数节流的情况下,为input绑定keyup事件处理函数,在控制台输出我输入的内容。

测试主要代码:

XHTML
 
1
<input id="search" type="text" name="search">

JavaScript

 

1
2
3
4
5
6 function queryData(text){
    console.log("搜索:" + text);
  }
var input = document.getElementById("search");
  input.addEventListener("keyup", function(event){ queryData(this.value);
});

结果如图:

可以看出,这种情况下,每按下一个键盘键,就输出了一次。短短的一些内容,输出了14次,如果每一次都是一次ajax查询请求的话就发了14个请求了。在性能上的消耗可想而知。

②使用基本的函数节流模式的情况。

测试主要代码:

XHTML
 
1
<input id="search" type="text" name="search">

JavaScript

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14 function queryData(text){
  console.log("搜索:" + text);
}
var input = document.getElementById("search");
input.addEventListener("keyup", function(event){
  throttle(queryData, null, 500, this.value);
  // queryData(this.value);
});
function throttle(fn,context,delay,text){
  clearTimeout(fn.timeoutId);
  fn.timeoutId = setTimeout(function(){
  fn.call(context,text);
  },delay);
}

结果如图:

可以看出,这种情况下,输入了好一些内容,只输出了一次,因为测试的时候设置了两次输入间隔是500ms,实际应用可根据情况设置。显然,这在性能上大大滴得到了优化。不过,这样的话,有一个新问题,如下图:

好吧,或许看不出端倪。其实问题就是,假如我不断地输入,输入了很多内容,但是我每两次之间的输入间隔都小于自己设置的delay值,那么,这个queryData搜索函数就一直得不到调用。实际上,我们更希望的是,当达到某个时间值时,一定要执行一次这个搜索函数。所以,就有了函数节流的改进模式。

③函数节流增强版

测试的主要代码:

XHTML
 
1
<input id="search" type="text" name="search">

JavaScript

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 function queryData(text){
  console.log("搜索:" + text);
}
var input = document.getElementById("search");
input.addEventListener("keyup", function(event){
  throttle(queryData, null, 500, this.value,1000);
  // throttle(queryData, null, 500, this.value);
  // queryData(this.value);
});
        
function throttle(fn,context,delay,text,mustApplyTime){
  clearTimeout(fn.timer);
  fn._cur=Date.now();  //记录当前时间
 
  if(!fn._start){      //若该函数是第一次调用,则直接设置_start,即开始时间,为_cur,即此刻的时间
    fn._start=fn._cur;
  }
  if(fn._cur-fn._start>mustApplyTime){ <br>            //当前时间与上一次函数被执行的时间作差,与mustApplyTime比较,若大于,则必须执行一次函数,若小于,则重新设置计时器
     fn.call(context,text);
     fn._start=fn._cur;
  }else{
    fn.timer=setTimeout(function(){
    fn.call(context,text);
    },deley);
  }
}

测试结果如图:

显然,连续的输入,到一定时间间隔之后,queryData函数必然会被调用,但是又不是频繁的调用。这既达到了节流的目的,又不会影响用户体验。

④进一步的优化

进一步的话,就是可以在调用throttle函数之前,先对输入的内容进行判断,若其值为空、值不变都不用再调用。这里就不详说了。

原文地址:http://web.jobbole.com/88733/

JS中的函数节流的更多相关文章

  1. JS中的函数节流throttle详解和优化

    JS中的函数节流throttle详解和优化在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(mousemove),这种事件有一个特点,在一个正常的操作中,有可能在一个短的 ...

  2. 谈谈JS中的函数节流

    好吧,一直在秋招中,都没怎么写博客了...今天赶紧来补一补才行...我发现,在面试中,讲到函数节流好像可以加分,尽管这并不是特别高深的技术,下面就聊聊吧! ^_^ 备注:以下内容部分来自<Jav ...

  3. [转] 谈谈JS中的函数节流

    函数节流的目的 从字面上就可以理解,函数节流就是用来节流函数从而一定程度上优化性能的.例如,DOM 操作比起非DOM 交互需要更多的内存和CPU 时间.连续尝试进行过多的DOM 相关操作可能会导致浏览 ...

  4. 【javascript】js中的函数节流和函数防抖

    一.概念解释  函数节流和函数防抖,两者都是优化高频率执行js代码的一种手段.  大家大概都知道旧款电视机的工作原理,就是一行行得扫描出色彩到屏幕上,然后组成一张张图片.由于肉眼只能分辨出一定频率的变 ...

  5. JS中的函数,Array对象,for-in语句,with语句,自定义对象,Prototype

    一)函数 A)JS中的函数的定义格式: function add(a,b) { var sum = a+b; document.write("两个数的和是:" + sum); // ...

  6. js中的函数,Date对象,Math对象和数组对象

    函数就是完成某个功能的一组语句,js中的函数由关键字 function + 函数名 + 一组参数定义;函数在定义后可以被重复调用,通常将常用的功能写成一个函数,利用函数可以使代码的组织结构更多清晰. ...

  7. js中getByClass()函数

    js中getByClass()函数进化史 对于js来说,我想每一个刚接触它的人都应该会抱怨:为什么没有一个通过class来获取元素的方法.尽管现在高版本的浏览器已经支持getElementsByCla ...

  8. JS中的函数、Bom、DOM及JS事件

    本期博主给大家带来JS的函数.Bom.DOM操作,以及JS各种常用的数据类型的相关知识,同时,这也是JavaScript极其重要的部分,博主将详细介绍各种属性的用法和方法. 一.JS中的函数 [函数的 ...

  9. node.js 中回调函数callback(转载),说的很清楚,看一遍就理解了

    最近在看 express,满眼看去,到处是以函数作为参数的回调函数的使用.如果这个概念理解不了,nodejs.express 的代码就会看得一塌糊涂.比如: 复制代码 代码如下: app.use(fu ...

随机推荐

  1. Js弹性漂浮广告代码

    <html><head><meta http-equiv="Content-Type" content="text/html; charse ...

  2. Android中多表的SQLite数据库(译)

    原文: Android SQLite Database with Multiple Tables 在上一篇教程Android SQLite Database Tutorial中,解释了如何在你的And ...

  3. Linux下MySql启动时报错

    /opt/mysql/support-files/mysql.server startmy_print_defaults: [ERROR] Found option without preceding ...

  4. (转载)iOS 多媒体

    音频:(音效.音乐) 在iOS中音频播放从形式上可以分为音效播放和音乐播放.前者主要指的是一些短音频播放,通常作为点缀音频,对于这类音频不需要进行进度.循环等控制.后者指的是一些较长的音频,通常是主音 ...

  5. C/C++中的隐式类型转换

    代码: #include <iostream> #include <cstdio> using namespace std; int main(int argc,char* a ...

  6. Oracle11g R2学习系列 之一安装篇

    前言 最近想去前同事推荐的一个Oracle相关的岗位竞争一下,由于之前没有使用Oracle的相关经验,所以决定学习一下,就算最终岗位应聘不成,至少也有了一些Oracle经验了,说不定哪天就用上了.再说 ...

  7. 一个商品练习的py

    #!/usr/bin/env python # coding=utf-8 # by 星空刺 qian = int(raw_input("请输入当前money:")) gongzi ...

  8. 第一个程序 - Windows程序设计(SDK)001

    愉快的开始 让编程改变世界 Change the world by program 编译器安装 我们经常说的 VS 指的就是 Microsoft Visual Studio 的简称,它是微软开发工具的 ...

  9. 远程调试 Azure 上的 Website

    让我们先检查一下使用的 Azure SDK 版本和 Visual Studio 版本.根据MSDN的介绍,Azure 的远程调试功能是在 Azure SDK 2.2 中加入的,所以请确保您的机器上安装 ...

  10. bootstrap 模态框动态加载数据

    .页面中添加modal <!-- 模态框(Modal) --> <div class="modal fade" id="showModal" ...