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

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

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

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

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

看了下原贴的两方法,觉得可以乐观锁的方法再写个,虽然最后对比结果和typeahead差不多。但过程还是挺有意思的,分享下思路

首先,浏览器事件间隔是没法改变的。所以我们只能改变回调函数的执行间隔。

乐观锁机制的流程是:

            do {                var _oldVal = _nowVal//记录基准值                //执行任务            } while (_oldVal != _nowVal)//比较 检查_nowVlau是否在执行任务的时候发生变化

  

根据这个结构,基本的设计思路就是:

  触发事件时启动一个“任务线程”,执行完指定的任务后,隔一段时间去检查没有没有发生后续事件(通过_oldVal与_nowVal判断),如果有重新执行任务,没有结束线程。

但有一个问题,“任务线程”同一时间只能执行一个,所以在触发事件的时候要做下判断。修改后的程序

    var _taskRun = false, _nowVal = 0, _oldVal = 0;    function eventFun() {        if (_taskRun) {            _nowVal++;        }        else {            _taskRun = true;            do {                var _oldVal = _nowVal//记录基准值                //执行任务            } while (_oldVal != _nowVal)//比较 检查_nowVlau是否在执行任务的时候发生变化            _taskRun = false;//执行结束重置状态变量            _nowVal = 0;        }    }

一切很顺利,但是要有间隔啊!js里可没有Thread.sleep,但有setTimeout,所以可以用setTimeout模拟sleep  

SO,Think.....了一会,不小心写了个异步do...while

        var _taskRun = false, _nowVal = 0, _oldVal = 0, _time = 100;        var _do = function (waitTime, funTsk) {//模拟do{}while(true);            var _endInner, _whileInner;            _whileInner = function (funcondition) {                _endInner = function (funEnd) {                    var _funWhile = function () {                        if (funcondition()) {                            _endInner(funEnd);                        } else {                            funEnd();                        }                    };                    var _runInner = function () {                        funTsk();                        setTimeout(_funWhile, waitTime);//延迟一段时间做判断                    };                    _runInner();                };                return {                    "end": _endInner                };            };            return { "while": _whileInner };        };        return function () {            if (_taskRun) {                _nowVal++;            }            else {                _taskRun = true;                _do(                    100,//间隔时间                     function () {                         _oldVal = _nowVal//记录基准值                         console.log(_oldVal);                     }                )                .while(                    function () {                        return _oldVal != _nowVal                    }                )                .end(                    function () {                        _taskRun = false;//执行结束重置状态变量                        _nowVal = 0;                    }                );            }        }

  

现在,基本OK了,但做了下测试,发觉间隔时间没有typeahead的准,怎么加事?

研究了下他的代码。发现高手的思路就不不一样。原来他是用当前时间去计算setTimeout的调用间隔的。SO出来的结果更加准确。

比如,设置间隔100秒,一个事件在距上个事件50秒的时候发生,为了保证每次100秒的间隔,这个事件的setTimeOut时间就应该设置成50秒而不是100秒

根据这个思路再修改了下代码,给出完整版:

    var _asynFun = function (func, wait) {        var context, args, result, _taskRun = false, _nowVal = 0, _oldVal = 0;        var _do = function (waitTime, funTsk) {//模拟do{}while(true);            var _endInner, _whileInner;            _whileInner = function (funcondition) {                _endInner = function (funEnd) {                    var _funWhile = function () {                        if (funcondition()) {                            _endInner(funEnd);                        } else {                            funEnd();                        }                    };                    var _runInner = function () {                        var _previous = new Date();                        result = funTsk.apply(context, args);                        var _remaining = waitTime - ((new Date()) - _previous);                        setTimeout(_funWhile, _remaining);//延迟一段时间做判断                    };                    _runInner();                };                return {                    "end": _endInner                };            };            return { "while": _whileInner };        };        return function () {            context = this;            args = arguments;            if (_taskRun) {                _nowVal++;            }            else {                _taskRun = true;                _do(                    wait,//间隔时间                     function () {                         _oldVal = _nowVal//记录基准值                         func();                     }                )                .while(                    function () {                        return _oldVal != _nowVal                    }                )                .end(                    function () {                        _taskRun = false;//执行结束重置状态变量                        _nowVal = 0;                    }                );            }            return result;        }    }

  

本文版权归作者和博客园共有,未经作者本人同意禁止任何形式的转载,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。

最后再贴出测试代码:

测试HTML页面

 

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