<!DOCTYPE html>
<html>
<head>
<title>Throttle</title>
</head>
<body>
<script type="text/javascript">
var count = 0;
var resizehandler = function () {
console.log(new Date().getTime());
console.log(count++);
}
var throttle = function (method, context){
clearTimeout(method.tId);
method.tId = setTimeout(function(){
method.call(context);
}, 100);
}
window.onresize = function(){
throttle(resizehandler, window);
};
</script>
</body>
</html>
我的疑问是为什么我在一直拖的情况下,一直没有打印出第一次出现的结果。
因为按照我的理解,执行到setTimeout()以后,应该在0.1秒后打印内容,但是一直拖就没结果,想知道为什么。
ringa_lee2017-04-10 15:06:20
因为你一直在 resize
. 此时你原来设定的事件处理器被 clearTimeout()
掉了,在连续的 resize
事件 (两次之间的间隔 < 100ms) 只有最后一次绑定的事件处理程序被调用。
设想 window 发生一次 resize
事件时,你在事件处理器中使用 setTimeout()
添加了一个将于 100ms 后调用的 resizeHandler()
函数,并且把这个 timeout 的 ID 存储在 resizeHandler.tId
里面。但是在 20ms 后, window 又发生了一次 resize
事件,此时首先 clearTimeout()
被调用,之前添加的 resizeHandler()
函数将不会得到执行。
所以对于连续发生的 resize
事件,我们可以得出什么结论呢? —只有当一次 resize
与下一次之间的时间间隔大于 100ms 时,这个 resizeHandler()
才会得到调用。这也就是你说的:
我的疑问是为什么我在一直拖的情况下,一直没有打印出第一次出现的结果。
今天早上在 CNBlogs 看到一个 throttle 实现 (http://www.cnblogs.com/dolphinX/p/3403821.html) 可以解决你所碰到的问题:
function throttle(method, delay, duration) {
var timer = null, begin = new Date();
return function () {
var context = this,
args = arguments,
current = new Date();
clearTimeout(timer);
if (current - begin >= duration) {
method.apply(context, args);
begin = current;
} else {
timer = setTimeout(function () {
method.apply(context, args);
}, delay);
}
};
}
(个人理解) 则在两次事件间隔时间大于 delay
时,或者事件发生时距离上一次重置 begin
不低于 duration
, 则 method
均能得到调用,其中,在后一种情况下,会把 begin
重置为事件发生的时刻。
调用该函数:
window.onresize = throttle(resizehandler, 100, 200);
除此之外,我也用 jQuery 写了一个 至多每隔一段时间 调用的 throttle 扩展:
(function ($) {
if (!$) { return; }
$.fn.throttle = function (eventName, f, dur) {
/// <param name="eventName" type="String"/>
/// <param name="f" type="Function"/>
/// <param name="dur" type="Number"/>
dur = dur || 400;
var that = this, g = function () {
setTimeout(function () {
that.each(f).one(eventName, g);
}, dur);
};
that.one(eventName, g);
return that;
}
})(window.jQuery);
(关于 jQuery.fn.one
, 详见 http://api.jquery.com/one/)
调用:
$(window).throttle("resize", resizeHandler, 100);
这样就可以在连续 resize 的情况下每 0.1s 打印输出内容,而在不 resize 的情况下则不输出任何内容。
以上。
(有用请支持/采纳。)