Undercore提供了方法throttle。从他们的文档:
创建并返回传递函数的一个新的节流版本,当重复调用该版本时,每等待毫秒最多只能调用一次原始函数。对于发生速度超过您所能跟上的速度的速率限制事件非常有用。
现在想象一下自动完成表单的情况。这意味着,如果在100ms窗口内键入"abc",则只发送对"a"的搜索,而不发送"bc"。
这是undercore.js方面的严重疏忽吗?你认为什么是清洁的解决方案?
对于此用例,您可能希望使用以下"buffer"函数,该函数将仅应用等待窗口内的最后一次调用。
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);
};
};
啊,我没有正确阅读文档!是的一个函数。
var test = _.debounce(function() { console.log('foo'); }, 3000);
然后,如果您多次调用test()
,您会注意到,只有在上一次调用后的三秒钟后,才会调用该函数。
这正是我们想要的。。。并且没有注意到就在文档上CCD_ 2的正下方。
Undercore文档,Lo Dash文档(什么是LoDash?)
看起来其他答案提到使用debounce而不是throttle。我找到了一个解决方案,它允许您在确保最后一次调用的同时保持节流行为(保持函数调用的进行)。
https://gist.github.com/ayushv512/a2f963bface38f5e2f6f6bba39bba9b9#file-节流js
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);
}
};
}
工作原理:
- 它最重要的是一个简单的throttle函数,如果最后一次调用的时间比
delay
长,则可以调用它 - 您可以设置一个标志CCD_ 4以使throttle函数确保最后一个调用将被调用;帧";
- 例如,如果将函数限制为每秒1次调用,则意味着它只会在上次调用超过1秒时激发
- 如果您在启用
ensure
标志的情况下调用throttle函数,而最后一次调用的时间不到1秒,例如600ms,则throttled函数只需设置一个超时值,以在400ms内调用该函数(wait = lastCall + delay - Date.now()
-此处,如果lastCall = 0
、delay = 1000
和Date.now() = 600
,则超时将发生在400
中) - 否则,如果你想把它当作一个简单的节流函数,就不要设置CCD_;帧";将被忽略
我认为这是一个优雅的解决方案,可以为简单的油门功能添加更多功能。我用它在编辑器中移动东西,同时保持重画在一定的帧速率,但仍然确保本应在帧之间发生的移动仍然被应用
我保留了一个idle
函数来处理这种类型的用户交互。这个想法是要求以规则的间隔调用一些函数(即,当在输入中按下某个键时);只要间隔过去而没有调用所述函数,就会触发单独的回调。这可能不是你想要的自动完成行为(你可能想在用户输入暂停之前开始搜索),但这是我过去使用过的一种方法。
不过,如果有人对此有更好的解决方案,我会洗耳恭听的!
是的,你说得对,它不适合自动完成表单。不过,我认为它适用于其他类型的东西。给出的示例是处理滚动事件。