JavaScript奇淫技巧(一) -----防抖动&&节流
实际中我们常会遇到绑定事件触发函数的情况,每次触发事件就调用函数执行逻辑或者是与后台交互
正常情况下这样做并没有问题,但是有的时候事件是高频触发的,而绑定的函数相对来说是一个代价比较大的函数,这样会降低程序的性能或者是影响用户体验.
举个例子:
有一个单据,需要根据金额的不同,展现不同的处理流程:如(0,10) 是A (10,100) 是B (100,1000)是C
并且流程应该是实时获取的.
可以这样实现 对金额输入框绑定一个keyUp事件 然后事件中触发获取流程的方法
1 $("#amount").keyup(function(){ 2 GetApprove($("#amount").val()) 3 }) 4 //其实应该这样写,可以避免在安卓捕获不到删除按钮的事件 5 document.getElementById("amount").addEventListener("input", function () { 6 GetApprove($("#amount").val()) 7 }, false); 8 9 var GetApprove=function(amount){ 10 //获取流程 11 }
这样的话,每次松开按键就会触发获取流程的方法,这样就能根据当前输入的金额获取到最新的数据了
但是这样有一个问题,当用户输入的金额是1000的时候,就会连续的触发四次请求,四次请求传递的金额是1, 10, 100, 1000
然而我们实际上只需要的是1000这次请求的返回结果,(并且如果你代码没有做任何处理的话,因为间隔时间短,再加上网络原因等,有可能请求返回的结果不是按发出的顺序返回,
可能是返回的10,1,100,1000 这样一个序列 最后导致用户获取的实际上是100的流程.这一个暂且不论在下一篇处理好了)
这样的话实际上浪费了三次请求,也就是说你的cpu压力加大了四倍
如何解决这个问题,可以这样处理:(防抖动Debounce)
var actionId=0; //设为全局变量 var GetApprove=function(amount){ clearTimeout(actionId); actionId=setTimeout(function() { //获取流程 }, 300); }
即每次操作都延时300ms处理,如果在300ms内中有新的操作则重新延时300ms并取消上一个操作.
这样的话就解决了频繁触发的问题,当用户正常输入1000的时候,虽然触发了1 10 100 1000四个操作 但是实际上只有最后一个操作真正被执行
查看了一下相关资料 可写这样一个方法
function Debounce(method,context){ clearTimeout(method.tId); method.tId=setTimeout(function(){ method.call(context); },500); }
当然,这样也还是存在一个问题,极端情况下,如果事件每隔250ms都被触发一次的话,那么事件就一直在创建--取消的过程,而没有事件真正的执行.
面对这种情况,我们可以这样处理 (节流 throttle)
这样的话 在一定时间内,只允许事件执行一次 ,其它的响应就被抛弃