js中的函数节流

2024-06-19 21:32
文章标签 函数 js 节流

本文主要是介绍js中的函数节流,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

函数节流的目的

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

函数节流的原理

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

函数节流的基本模式

复制代码
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事件处理函数,在控制台输出我输入的内容。

测试主要代码:

复制代码
HTMl:<input id="search" type="text" name="search">
JS:<script>function queryData(text){console.log("搜索:" + text);}var input = document.getElementById("search");input.addEventListener("keyup", function(event){ queryData(this.value);});</script>        
复制代码

结果如图:

911587-20161011213630359-1312990595.png

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

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

测试主要代码:

复制代码
HTML:<input id="search" type="text" name="search">
JS:<script>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);}</script>
复制代码

结果如图:

911587-20161011213647187-788070101.png

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

911587-20161011213707609-1429985338.png

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

③函数节流增强版

测试的主要代码:

复制代码
HTML:<input id="search" type="text" name="search">
JS:<script>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){ 
//当前时间与上一次函数被执行的时间作差,与mustApplyTime比较,若大于,则必须执行一次函数,若小于,则重新设置计时器fn.call(context,text);fn._start=fn._cur;}else{fn.timer=setTimeout(function(){fn.call(context,text);},delay);}}</script>
复制代码

测试结果如图:

911587-20161011213724437-1308054011.png

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

④进一步的优化

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

 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) {if (!text) return;console.log(text);clearTimeout(fn.timer);fn._cur = Date.now();  //记录当前时间if (!fn._start) {      //若该函数是第一次调用,则直接设置_start,即开始时间,为_cur,即此刻的时间fn._start = fn._cur;}if (fn._cur - fn._start > mustApplyTime) {//当前时间与上一次函数被执行的时间作差,与mustApplyTime比较,若大于,则必须执行一次函数,若小于,则重新设置计时器fn.call(context, text);fn._start = fn._cur;} else {fn.timer = setTimeout(function () {fn.call(context, text);}, delay);}}

  

这篇关于js中的函数节流的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1076201

相关文章

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

PHP应用中处理限流和API节流的最佳实践

《PHP应用中处理限流和API节流的最佳实践》限流和API节流对于确保Web应用程序的可靠性、安全性和可扩展性至关重要,本文将详细介绍PHP应用中处理限流和API节流的最佳实践,下面就来和小编一起学习... 目录限流的重要性在 php 中实施限流的最佳实践使用集中式存储进行状态管理(如 Redis)采用滑动

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Python Counter 函数使用案例

《PythonCounter函数使用案例》Counter是collections模块中的一个类,专门用于对可迭代对象中的元素进行计数,接下来通过本文给大家介绍PythonCounter函数使用案例... 目录一、Counter函数概述二、基本使用案例(一)列表元素计数(二)字符串字符计数(三)元组计数三、C

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N

MySQL中REPLACE函数与语句举例详解

《MySQL中REPLACE函数与语句举例详解》在MySQL中REPLACE函数是一个用于处理字符串的强大工具,它的主要功能是替换字符串中的某些子字符串,:本文主要介绍MySQL中REPLACE函... 目录一、REPLACE()函数语法:参数说明:功能说明:示例:二、REPLACE INTO语句语法:参数

python中update()函数的用法和一些例子

《python中update()函数的用法和一些例子》update()方法是字典对象的方法,用于将一个字典中的键值对更新到另一个字典中,:本文主要介绍python中update()函数的用法和一些... 目录前言用法注意事项示例示例 1: 使用另一个字典来更新示例 2: 使用可迭代对象来更新示例 3: 使用

Python lambda函数(匿名函数)、参数类型与递归全解析

《Pythonlambda函数(匿名函数)、参数类型与递归全解析》本文详解Python中lambda匿名函数、灵活参数类型和递归函数三大进阶特性,分别介绍其定义、应用场景及注意事项,助力编写简洁高效... 目录一、lambda 匿名函数:简洁的单行函数1. lambda 的定义与基本用法2. lambda

Python 函数详解:从基础语法到高级使用技巧

《Python函数详解:从基础语法到高级使用技巧》本文基于实例代码,全面讲解Python函数的定义、参数传递、变量作用域及类型标注等知识点,帮助初学者快速掌握函数的使用技巧,感兴趣的朋友跟随小编一起... 目录一、函数的基本概念与作用二、函数的定义与调用1. 无参函数2. 带参函数3. 带返回值的函数4.