码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2014-12-06 16:43:08      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:blog   http   io   ar   os   sp   for   java   on   

看了下园友的一帖子: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;
        }
    }

  

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

最后再贴出测试代码:

bubuko.com,布布扣测试HTML页面

 

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

标签:blog   http   io   ar   os   sp   for   java   on   

原文地址:http://www.cnblogs.com/Grart/p/4148383.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!