//多次触发某个动作,如onresize事件,窗口变化时会连续触发多次resize事件,消耗性能。可采取在一定时间内触发一次,取消掉无效的触发动作的执行。
//实现方式1:: 指定时间间隔调用delayMethod返回的函数
//每次调用时,清除上一次的定时器,重新设置一个定时器
function delayMethod(method,wait){ var timerId = null; return function(){ var args = arguments; var context = this; clearTimeout(timerId); timerId = setTimeout(function(){ method.apply(context,args); },wait); } } } //调用方式 var wrapHanlder = delayMethod(evtHandler,500); $(window).on("resize",function(){ var params = {}; wrapHanlder(params); } })
underscore中的实现:
如果已经设置过定时器则不再设置,等待设定的时间间隔后执行操作,执行完成后重置定时器,timer=null,下次再出发该操作时,再设置定时器。
/** * 函数节流 * @param func 事件处理函数 * @param wait 延迟的时间间隔 * @param immediate 是否立即执行,默认false * @return 返回事件处理函数 */ function debounce(func, wait, immediate) { var timeout, args, context, timestamp, result; //immediate默认为false // 当wait指定的时间间隔期间多次调用_.debounce返回的函数,则会不断更新timestamp的值,导致last < wait && last >= 0一直为true,从而不断启动新的计时器延时执行func var later = function() { var last = +new Date() - timestamp; console.log("last 时间间隔 < 设置的 wait",last,wait); if (last < wait && last >= 0) { timeout = setTimeout(later, wait - last); } else { timeout = null; if (!immediate) { result = func.apply(context, args); if (!timeout) context = args = null; } } }; return function() { context = this; args = arguments; timestamp = +new Date(); // 第一次调用该方法时,且immediate为true,则调用func函数 var callNow = immediate && !timeout; // 在wait指定的时间间隔内首次调用该方法,则启动计时器定时调用func函数 console.log("timeout",timeout); if (!timeout) { console.log("timeout为null时,重新设置定时器"); timeout = setTimeout(later, wait); } if (callNow) { result = func.apply(context, args); context = args = null; } return result; }; };