“如何稀释scroll事件”的思考

看了下园友的一帖子:http://www.cnblogs.com/xzhang/p/4145697.html#commentform

本来以为是很简单的问题,但仔细想想还挺有意思的。简单的说就是增加事件触发的间隔时间。

比如在浏览器状态了事件是1毫秒调用一次,转换成100毫秒调用一次。

看了下原贴的两方法,觉得可以乐观锁的方法再写个,结果对比后发觉和typeahead差不多。贴下代码和测试页面。看那位能指点下写的更好。:)

    var _lazyRun = function (func, wait) {
        var _preIndex = 0, _nowIndex = 1, _timer, _fnCur, _context, _result;
        var _fn1 = function () {
            if (_preIndex < _nowIndex) {
                _fnCur = _fn2;
                clearTimeout(_timer);
                var _previous = new Date();
                _preIndex = _nowIndex;
                _result = func.apply(_context, _args);
                var _remaining = wait - ((new Date()) - _previous);

                if (_remaining < 0) {
                    _result = func.apply(_context, _args);
                } else {
                    _timer = setTimeout(_fn1, _remaining);//脱离线程
                }
            } else {
                _fnCur = _fn1;
                _preIndex = 0, _nowIndex = 1;
            }
            return _result;

        };
        var _fn2 = function () {
            _nowIndex++;
            return _result;
        };
        _fnCur = _fn1;
        return function () {
            _context = this;
            _args = arguments;
            _result = _fnCur.apply(_context, _args);
            return _result;
        };
    };

  

测试页面

<html>
<head>
    <title>
        “如何稀释scroll事件”引出的问题
    </title>
    <meta charset="utf-8">
    <style type="text/css">
        #box {
            border: 2px solid #f60;
            margin: 0 auto;
        }
    </style>
</head>
<body>
    <input id="waitTime" type="text" value="100" onchange="onscrollTest()" />
    <select id="sel" onchange="onscrollTest()">
        <option value="1">使用_lazyRun</option>
        <option value="2">使用debounce</option>
        <option value="3">使用throttle </option>
    </select>
    <div id="outDiv"></div>
    <div id="box" style="width:600px; height:6000px">
    </div>
</body>
</html>

<script type="text/javascript">
    var _lazyRun = function (func, wait) {
        var _preIndex = 0, _nowIndex = 1, _timer, _fnCur, _context, _result;
        var _fn1 = function () {
            if (_preIndex < _nowIndex) {
                _fnCur = _fn2;
                clearTimeout(_timer);
                var _previous = new Date();
                _preIndex = _nowIndex;
                _result = func.apply(_context, _args);
                var _remaining = wait - ((new Date()) - _previous);

                if (_remaining < 0) {
                    _result = func.apply(_context, _args);
                } else {
                    _timer = setTimeout(_fn1, _remaining);//脱离线程
                }
            } else {
                _fnCur = _fn1;
                _preIndex = 0, _nowIndex = 1;
            }
            return _result;

        };
        var _fn2 = function () {
            _nowIndex++;
            return _result;
        };
        _fnCur = _fn1;
        return function () {
            _context = this;
            _args = arguments;
            _result = _fnCur.apply(_context, _args);
            return _result;
        };
    };

    //**************************underscore.js 的 debounce
    /**
    * [debounce description]
    * @param  {[type]} func      [回调函数]
    * @param  {[type]} wait      [等待时长]
    * @param  {[type]} immediate [是否立即执行]
    * @return {[type]}           [description]
    */
    var _ = {};
    _.debounce = function (func, wait, immediate) {
        var timeout, args, context, timestamp, result;

        var later = function () {
            var last = _.now() - timestamp;

            //小于wait时间,继续延迟wait-last执行later,知道last >= wait才执行func
            if (last < wait && last > 0) {
                timeout = setTimeout(later, wait - last);
            } else {
                timeout = null;
                if (!immediate) {
                    result = func.apply(context, args);

                    if (!timeout) context = args = null;
                }
            }
        };

        return function () {
            context = this;
            args = arguments;
            timestamp = _.now();
            //是否立即执行
            var callNow = immediate && !timeout;

            if (!timeout) timeout = setTimeout(later, wait);

            if (callNow) {
                result = func.apply(context, args);
                context = args = null;
            }

            return result;
        };
    };

    _.now = Date.now || function () {
        return new Date().getTime();
    };

    //**************************typeahead.js 的 throttle
    var throttle = function (func, wait) {
        var context, args, timeout, result, previous, later;
        previous = 0;
        later = function () {
            previous = new Date();
            timeout = null;
            result = func.apply(context, args);
        };
        return function () {
            var now = new Date(),
                remaining = wait - (now - previous);
            context = this;
            args = arguments;
            if (remaining <= 0) {   //如果大于间隔时间(wait)
                clearTimeout(timeout);
                timeout = null;
                previous = now;
                result = func.apply(context, args);
            } else if (!timeout) {  //小于,延时调用later
                timeout = setTimeout(later, remaining);
            }
            return result;
        };
    };

    //**************************测试***********************************
    var _testCount = 0;
    var _test = function () {
        console.log(_.now())
        _testCount++;
        //console.log(window.scrollY || document.documentElement.scrollTop);

    };
    function onscrollTest() {
        _testCount = 0;
        var _waitTime = document.getElementById("waitTime").value;
        switch (document.getElementById("sel").value) {
            case "1"://_lazyRun
                document.getElementById("outDiv").innerText = "use _lazyRun function ,wait time is " + _waitTime;
                window.onscroll = _lazyRun(_test, _waitTime);
                break;
            case "2"://debounce
                document.getElementById("outDiv").innerText = "use debounce function ,wait time is " + _waitTime;
                window.onscroll = _.debounce(_test, _waitTime);
                break;
            case "3"://throttle

                document.getElementById("outDiv").innerText = "use throttle function ,wait time is " + _waitTime;
                window.onscroll = throttle(_test, _waitTime);
                break;
        };
        console.clear();

    }
    onscrollTest();
</script>

  

时间: 2024-10-13 14:42:55

“如何稀释scroll事件”的思考的相关文章

“如何稀释scroll事件”的思考(不小心写了个异步do...while)

看了下园友的一帖子:http://www.cnblogs.com/xzhang/p/4145697.html#commentform 本来以为是很简单的问题,但仔细想想还挺有意思的.简单的说就是增加事件触发的间隔时间. 比如在浏览器的事件是1毫秒调用一次,转换成100毫秒调用一次. 看了下原贴的两方法,觉得可以乐观锁的方法再写个,虽然最后对比结果和typeahead差不多.但过程还是挺有意思的,分享下思路 首先,浏览器事件间隔是没法改变的.所以我们只能改变回调函数的执行间隔. 乐观锁机制的流程是

“如何稀释scroll事件”引出的问题

背景:我在segmentfault提了个问题如何稀释onscroll事件,问题如下: 面试时问到这个问题,是这样的:    面试官问一个关于滚动到某个位置的时候出现一个顶部的导航栏,答完之后,她接着问一滚动onscroll就会执行很多很多次,如何稀释它?为了确定她说的是“稀释”,我让她重复了遍,我给出的解决方法是,用一个变量,在事件处理的时候让它自增,判断达到一定大小就执行一次实际的事件: var i = 0; // 累积变量 window.onscroll = function(){ i++;

javascript中的scroll事件

window.addEventListener('scroll',function(){ if(document.compatMode == "CSS1Compat") { alert(document.documentElement.scrollTop); } else { alert(document.body.scrollTop); } },false); 虽然scroll事件是在window对象上发生的,但它事件表示的则是页面中相应元素的变化.在混杂模式中,可以通过<bo

scroll事件实现监控滚动条并分页显示示例(zepto.js)

scroll事件实现监控滚动条并分页显示示例(zepto.js  ) 需求:在APP落地页上的底部位置显示此前其他用户的购买记录,要求此div盒子只显示3条半,但一页有10条,div内的滑动条滑到一页底部自动加载下一页并发加载埋点. 实现:首先理解三个概念,分别是contentH,viewH,scrollTop. contentH:即所要滑动的元素内容的高度,包括可见部分以及滚动条下面的不可见部分. ViewH:即我们看到的这个DIV的高度,不包括可见部分也不包括滚动条下面的不可见部分. scr

scroll事件在IE,chrome,FF中的行为表现

周末想做一个滚动加载图片的效果.在IE,chrome,FF中验证时,忽然发现了一个有趣的问题. 问题是这样的: 1.     我发现鼠标滚动一次,scroll事件的处理函数执行的次数不一样. 2.     滚动的距离也不一样. 3.     点击滚动条滚动时,执行次数,滚动距离也不一样. 经过验证:        执行次数: 在IE5,6,7,8下,滚动一次,函数执行4次: 在IE9,10以上版本执行1次: 在chrome下,只执行一次.(chrome版本号:34.0.1847.116 m) 在

扩展jquery scroll事件,支持 scroll start 和 scroll stop

参考地址: http://www.ghugo.com/special-scroll-events-for-jquery/ javascript里有一个事件是滚动事件,只要拖动滚动条,就会触发事件. 用jquery的话,这个事件scroll 可以查看jquery api :http://api.jquery.com/scroll/ 但scroll 事件有一个缺陷,就是只能判断滚动条滚动,而不能监控滚动条停止滚动时的事件. 现用jquery扩展一下scroll 事件,新增 不多说,直接上代码实在点.

jQuery事件:scroll事件

scroll事件:滚动元素时或者是使用scroll()方法会触发scroll事件 scroll()方法 触发选中元素的scroll事件 $(selector).scroll()//无参数 规定scroll事件被触发后的函数 $(selector).scroll( function ) function:js Function对象 详情

jQuery scroll事件实现监控滚动条分页示例(转)

这篇文章主要介绍了jQuery scroll事件实现监控滚动条分页简单示例,使用ajax加载,同时介绍了(document).height()与$(window).height()的区别,需要的朋友可以参考下. scroll事件适用于window对象,但也可滚动iframe框架与CSS overflow属性设置为scroll的元素. 1 $(document).ready(function () { //本人习惯这样写了 2 $(window).scroll(function () { 3 //

jquery scroll事件

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>scroll Demo</title