JS函数节流和函数防抖问题分析
2018-03-29 21:11
393 查看
问题1:如果实现了dom拖拽功能,但是在绑定拖拽事件的时候发现每当元素稍微移动一点便触发了大量的回调函数,导致浏览器直接卡死,这个时候怎么办?
问题2:如果给一个按钮绑定了表单提交的post事件,但是用户有些时候在网络情况极差的情况下多次点击按钮造成表单重复提交,如何防止多次提交的发生?
为了应对如上场景,便出现了 函数防抖 和 函数节流 两个概念,总的来说:这两个方法是在时间轴上控制函数的执行次数。
生活中的实例: 如果有人进电梯(触发事件),那电梯将在10秒钟后出发(执行事件监听器),这时如果又有人进电梯了(在10秒内再次触发该事件),我们又得等10秒再出发(重新计时)。
生活中的实例: 我们知道目前的一种说法是当 1 秒内连续播放 24 张以上的图片时,在人眼的视觉中就会形成一个连贯的动画,所以在电影的播放中基本是以每秒 24 张的速度播放的,为什么不 100 张或更多?是因为 24 张就可以满足人类视觉需求的时候,100 张就会显得很浪费资源。
(1)如果触发事件的频率是 0.5s/次 ,那么函数防抖,如图:
因为始终没法等一秒钟就被再次触发了,所以最终没有一次事件是成功的。
函数节流,如图:
因为控制了最多一秒一次,频率为 0.5s/次 ,所以每一秒钟就有一次事件作废。最终控制成 1s/次。
(2)如果触发事件的频率是 2s/次 ,那么
函数防抖,如图:
因为 2s/次已经大于了规定的最小时间,所以每计时两秒便触发一次。
函数节流,如图:
同样, 2s/次 大于了最小时间规定,所以每一次触发都生效。
(1)给按钮加函数防抖防止表单多次提交。
(2)对于输入框连续输入进行AJAX验证时,用函数防抖能有效减少请求次数。
(3)判断 scroll 是否滑到底部, 滚动事件 + 函数防抖
总的来说,适合多次事件,一次响应的情况
对于函数节流,有如下几个场景:
(1)游戏中的刷新率
(2)DOM元素拖拽
(3)Canvas画笔功能
总的来说,适合大量事件按时间做平均分配触发。
之所以返回一个函数,因为防抖本身更像是一个函数修饰,所以就做了一次函数柯里化。里面也用到了闭包,闭包的变量是 timer 。
函数节流:
实现的一个简单的函数节流,结果是一秒打出一次boom。
问题2:如果给一个按钮绑定了表单提交的post事件,但是用户有些时候在网络情况极差的情况下多次点击按钮造成表单重复提交,如何防止多次提交的发生?
为了应对如上场景,便出现了 函数防抖 和 函数节流 两个概念,总的来说:这两个方法是在时间轴上控制函数的执行次数。
1、函数防抖(debounce)
概念: 在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。生活中的实例: 如果有人进电梯(触发事件),那电梯将在10秒钟后出发(执行事件监听器),这时如果又有人进电梯了(在10秒内再次触发该事件),我们又得等10秒再出发(重新计时)。
2、函数节流(throttle)
概念: 规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。生活中的实例: 我们知道目前的一种说法是当 1 秒内连续播放 24 张以上的图片时,在人眼的视觉中就会形成一个连贯的动画,所以在电影的播放中基本是以每秒 24 张的速度播放的,为什么不 100 张或更多?是因为 24 张就可以满足人类视觉需求的时候,100 张就会显得很浪费资源。
3、分析图
假设,我们观察的总时间为10秒钟,规定1秒作为一次事件的最小间隔时间。(1)如果触发事件的频率是 0.5s/次 ,那么函数防抖,如图:
因为始终没法等一秒钟就被再次触发了,所以最终没有一次事件是成功的。
函数节流,如图:
因为控制了最多一秒一次,频率为 0.5s/次 ,所以每一秒钟就有一次事件作废。最终控制成 1s/次。
(2)如果触发事件的频率是 2s/次 ,那么
函数防抖,如图:
因为 2s/次已经大于了规定的最小时间,所以每计时两秒便触发一次。
函数节流,如图:
同样, 2s/次 大于了最小时间规定,所以每一次触发都生效。
4、应用场景
对于函数防抖,有以下几种应用场景:(1)给按钮加函数防抖防止表单多次提交。
(2)对于输入框连续输入进行AJAX验证时,用函数防抖能有效减少请求次数。
(3)判断 scroll 是否滑到底部, 滚动事件 + 函数防抖
总的来说,适合多次事件,一次响应的情况
对于函数节流,有如下几个场景:
(1)游戏中的刷新率
(2)DOM元素拖拽
(3)Canvas画笔功能
总的来说,适合大量事件按时间做平均分配触发。
5、实现源码:
函数防抖:function debounce(fn, wait) { var timer = null; return function() { var context = this; var args = arguments; if (timer) { clearTimeout(timer); timer = null; }; timer = setTimeout(function() { fn.apply(context, args); }, wait); }; } var fn = function() { console.log('boom'); } setInterval(debounce(fn, 500), 1000) // 第一次在1500ms后触发,之后每1000ms触发一次 setInterval(debounce(fn, 2000), 1000) // 不会触发一次(我把函数防抖看出技能读条,如果读条没完成就用技能,便会失败而且重新读条)
之所以返回一个函数,因为防抖本身更像是一个函数修饰,所以就做了一次函数柯里化。里面也用到了闭包,闭包的变量是 timer 。
函数节流:
function throttle(fn, gapTime) { let _lastTime = null; return function() { let _nowTime = new Date(); if (_nowTime - _lastTime > gapTime || !_lastTime) { fn(); _lastTime = _nowTime; }; }; } let fn = () => { console.log('boom'); } setInterval(throttle(fn, 1000), 10);
实现的一个简单的函数节流,结果是一秒打出一次boom。
相关文章推荐
- JS函数节流和函数防抖问题分析
- oracle分析函数问题1
- C++ 二级指针、函数指针与数组复合类型的问题分析
- 一个小sql的问题记录 对分析函数的应用
- 关于动态存储分配函数的调用,在已经过排序的数组中查找及删除内容的操作,余数的分析,删除字符数组中的空格,对链表的逆置,在源字符串中查找子字符串的个数,函数指针以及函数的调用,循环赋值带来的问题以及插入
- 分析C++方式构造函数调用虚函数的问题
- 关于rownum排序分页会比分析函数排序快的问题。。。
- Javascript-Mozilla和IE中的一个函数直接量的问题分析
- 通过临时表解决--未能为视图或函数解释分析分配辅助表,超过了查询中表地最大数目(260)--的问题
- 和表值函数连接引发的性能问题分析
- [转载] MFC下关于“建立空文档失败”问题的分析二 ---ProcessShellCommand()函数分析
- C++虚函数分析[1]--同名函数继承二义性问题
- 和表值函数连接引发的性能问题分析
- 从内存角度分析:数组删除自己内部指定对象和通过函数形参改值问题
- php中mkdir()函数的权限问题分析
- DllMain中不当操作导致死锁问题的分析--进程对DllMain函数的调用规律的研究和分析
- SQL SERVER修改函数名容易引发的问题分析
- js函数节流 函数去抖来解决多次触发事件的问题
- Linux C语言 函数return 0 程序却coredump, 问题分析
- 虚函数相关问题分析