首页 > JavaScript throttle 的疑问

JavaScript throttle 的疑问

<!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秒后打印内容,但是一直拖就没结果,想知道为什么。


因为你一直在 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 的情况下则不输出任何内容。

以上。
(有用请支持/采纳。)


一直拖就一直 clearTimeout 了,所以不打印了

【热门文章】
【热门文章】