underscorejs庫:https://www.underscorejs.cn/debounce
- _.debounce(function, wait, [immediate])
返回 function 函數(shù)的防反跳版本, 將延遲函數(shù)的執(zhí)行(真正的執(zhí)行)在函數(shù)最后一次調(diào)用時(shí)刻的 wait 毫秒之后. 對(duì)于必須在一些輸入(多是一些用戶操作)停止到達(dá)之后執(zhí)行的行為有幫助。 例如: 渲染一個(gè) Markdown 格式的評(píng)論預(yù)覽, 當(dāng)窗口停止改變大小之后重新計(jì)算布局, 等等.
在 wait 間隔結(jié)束時(shí),將使用最近傳遞給 debounced(去抖動(dòng))函數(shù)的參數(shù)調(diào)用該函數(shù)。
傳參 immediate 為 true, debounce 會(huì)在 wait 時(shí)間間隔的開始調(diào)用這個(gè)函數(shù) 。(注:并且在 waite 的時(shí)間之內(nèi),不會(huì)再次調(diào)用。)在類似不小心點(diǎn)了提交按鈕兩下而提交了兩次的情況下很有用。
var lazyLayout = _.debounce(calculateLayout, 300);
$(window).resize(lazyLayout);
如果需要取消預(yù)定的 debounce ,可以在 debounce 函數(shù)上調(diào)用 .cancel()。
- _.throttle(function, wait, [options])
創(chuàng)建并返回一個(gè)像節(jié)流閥一樣的函數(shù),當(dāng)重復(fù)調(diào)用函數(shù)的時(shí)候,至少每隔 **wait **毫秒調(diào)用一次該函數(shù)。對(duì)于想控制一些觸發(fā)頻率較高的事件有幫助。
默認(rèn)情況下,throttle 將在你調(diào)用的第一時(shí)間盡快執(zhí)行這個(gè) function,并且,如果你在** wait **周期內(nèi)調(diào)用任意次數(shù)的函數(shù),都將盡快的被覆蓋。如果你想禁用第一次首先執(zhí)行的話,傳遞{leading: false},還有如果你想禁用最后一次執(zhí)行的話,傳遞{trailing: false}。
var throttled = _.throttle(updatePosition, 100);
$(window).scroll(throttled);
如果需要取消預(yù)定的 throttle ,可以在 throttle 函數(shù)上調(diào)用 .cancel()。
function restArguments(func, startIndex) {
startIndex = startIndex == null ? func.length - 1 : +startIndex;
return function() {
var length = Math.max(arguments.length - startIndex, 0),
rest = Array(length),
index = 0;
for (; index < length; index++) {
rest[index] = arguments[index + startIndex];
}
switch (startIndex) {
case 0: return func.call(this, rest);
case 1: return func.call(this, arguments[0], rest);
case 2: return func.call(this, arguments[0], arguments[1], rest);
}
var args = Array(startIndex + 1);
for (index = 0; index < startIndex; index++) {
args[index] = arguments[index];
}
args[startIndex] = rest;
return func.apply(this, args);
};
}
var now = Date.now || function() {
return new Date().getTime();
};
export function debounce(func, wait, immediate) {
var timeout, previous, args, result, context;
var later = function() {
var passed = now() - previous;
if (wait > passed) {
timeout = setTimeout(later, wait - passed);
} else {
timeout = null;
if (!immediate) result = func.apply(context, args);
// This check is needed because `func` can recursively invoke `debounced`.
if (!timeout) args = context = null;
}
};
var debounced = restArguments(function(_args) {
context = this;
args = _args;
previous = now();
if (!timeout) {
timeout = setTimeout(later, wait);
if (immediate) result = func.apply(context, args);
}
return result;
});
debounced.cancel = function() {
clearTimeout(timeout);
timeout = args = context = null;
};
return debounced;
}
export function throttle(func, wait, options) {
var timeout, context, args, result;
var previous = 0;
if (!options) options = {};
var later = function() {
previous = options.leading === false ? 0 : now();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
var throttled = function() {
var _now = now();
if (!previous && options.leading === false) previous = _now;
var remaining = wait - (_now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = _now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
throttled.cancel = function() {
clearTimeout(timeout);
previous = 0;
timeout = context = args = null;
};
return throttled;
}