Underscore提供了方法,throttle。来自他们的文档:
创建并返回所传递函数的新的、受限制的版本,当重复调用时,实际上每等待毫秒最多只会调用一次原始函数。对于发生速度比您跟不上的速度更快的速率限制事件很有用。
现在想象一下自动完成表单的情况。这意味着,如果在 100 毫秒窗口内键入“abc”,则只会发送对“a”的搜索,而不是“bc”。
这是 underscore.js 的严重疏忽吗?您建议什么作为干净的解决方案?
对于此用例,您可能需要使用以下“缓冲区”函数,该函数将仅应用等待窗口内的最后一个调用。
https://gist.github.com/2484196
_.buffer = function(func, wait, scope) {
var timer = null;
return function() {
if(timer) clearTimeout(timer);
var args = arguments;
timer = setTimeout(function() {
timer = null;
func.apply(scope, args);
}, wait);
};
};
啊,我没有正确阅读文档!有 is 一个函数可以实现此目的。
var test = _.debounce(function() { console.log('foo'); }, 3000);
然后,如果您调用
test()
几次,您会注意到,只有在 last 调用后三秒后,才会调用该函数。
这正是我们都在寻找的东西......但没有注意到就在文档的throttle
下方。
Underscore 文档
const throttle = (func, limit) => {
let lastFunc;
let lastRan;
return function() {
const context = this;
const args = arguments;
if (!lastRan) {
func.apply(context, args)
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function() {
if ((Date.now() - lastRan) >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
}
}
function throttle(f, delay = 0, ensure = false) {
let lastCall = Number.NEGATIVE_INFINITY;
let wait;
let handle;
return (...args) => {
wait = lastCall + delay - Date.now();
clearTimeout(handle);
if (wait <= 0 || ensure) {
handle = setTimeout(() => {
f(...args);
lastCall = Date.now();
}, wait);
}
};
}
工作原理:
它首先是一个简单的节流函数,如果最后一次调用的时间早于
delay
,您可以调用它您可以设置一个标志
ensure
ensure
wait = lastCall + delay - Date.now()
- 这里如果 lastCall = 0
和 delay = 1000
和 Date.now() = 600
那么超时将在 400
内发生)否则,如果您希望将其视为简单的节流功能,只需不要设置 ensure