微信号:FrontDev

介绍:分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯

双阈值对抗数据抖动

2016-06-24 20:45 前端大全

(点击上方公众号,可快速关注)

作者:伯乐在线专栏作者 - 尘钥

链接:http://web.jobbole.com/86427/

点击 → 了解如何加入专栏作者


今天我想分享一下我在近期有关阈值的一些技巧,因为笔者是一名前端开发,因此下面的demo笔者使用js编写,但是这篇文章中的技巧是一种思想并不限于js。


我们在写程序的时候经常会发现这样一种情况:我们需要根据某一个变量的值属于哪个区间来控制分支的走向,比如下面的代码:


function changeText(num){

    if(num>100){

        taskA();

    }else{

        taskB();

    }      

}


上面的代码逻辑很简单,当num大于100时,执行taskA函数,反之执行taskB函数(假设taskA、taskB内部实现都有防止连续执行的处理)。对于大多数的场景,这样的实现是足以满足判断的。但是单元测试通过不代表这个模块可以在工程中的任何场景使用。


 


试想这样一种情况:我的页面上有一个DOM元素,taskA()负责将内容修改为“123456”,taskB()负责将内容修改为“654321”。到目前为止上面的代码都可以正常运行,但是接下来就是在什么场合调用changeText()了。比如这里有一个水位监测系统,水位高于100cm时执行任务A(可能是红灯亮)反之执行任务B(可能是路灯亮),水位刚好为100 左右时,随着风浪水位不断在阈值两边变化,taskA和taskB即使有防止连续执行的处理,也会交替执行红灯路灯来回变化不断的闪烁。两个任务就会被频繁改写。我模拟的是一个抽象的例子,在开发中比如鼠标移动、鼠标滚轮、长连接、input事件等等场合都有可能遇到频繁调用+阈值判断的情形。那么我们如何防止频繁经过临界点,造成的性能损耗和不好的用户体验呢。


接下来我将介绍双阈值的方式。用在这个例子中使水位在100 这个临界值变动的时候加入方向性,简单来说从小于100 到超过100的时候绿灯灭、红灯亮(开始警告);但是水位从高于100 到小于100时,并不马上红灯灭、绿灯亮。而是将从上到下的阈值另设定为95(假定风浪造成的数据抖动为5cm),来保证在警报状态下,水位由高到低变化时,直到水位降到95cm时才解除警报(绿灯亮、红灯灭)。这样就在不同的两个状态下拥有了各自的阈值。如下图:



如果用代码该怎么实现呢?既然两个阈值的使用依赖于当前所处的状态。那么我们就要“记录”状态,最简单的方法是由原有的一个参数增加一个状态参数:


/*双阈值*/

function doubleTh1(status, num){

    var rt = '';

    if(status == 'downToUp'){

        if(num>100){

            rt = taskA();

        }else{

            rt = taskB();

        }

    }else if(status == 'upToDown'){

        if(num <= 95){

            rt = taskB();

        }else{

            rt = taskA();

        }

    }

    return rt;

}


单元测试:



这只是对双阈值概念的初级实现,我们不应该每次传递状态值,状态的记录应该交给函数自身记录,每次的状态依赖上一次返回的结果。我们可以通过闭包来写一个双阈值函数的生成器:


function doubleTh2(th1, th2, cb1, cb2){

    var status = 's1';

 

    return function (num){

        var rt = "";

        if(status == 's1' && num > th1){

            status = 's2';

        }

        if(status == 's2' && num <= th2){

            status = 's1';

        }

 

        if(status == 's1'){

            rt = cb2 && cb2()

        }else if(status == 's2'){

            rt = cb1 && cb1();

        }

 

        return rt;

    };

}


调用:


var th2 = ts.doubleTh2(100, 95, function (status){

      console.log('call taskA');

    return 'taskA';

  }, function (status){

      console.log('call taskB');

    return 'taskB';

  });

 

  it('值为98时应该执行 taskB', function() {

    expect(th2(98)).to.be.equal("taskB");

  });

     


总结:


这样我们就完成了一个双阈值的函数,我们使用这样的函数来防止位于临界值的数据抖动。当然感兴趣的同学可以扩展为多级的判断函数。



专栏作者简介 ( 点击 → 加入专栏作者 


尘钥:前端广告人,偏前的前端开发。奋斗在浏览器的战场微博: http://weibo.com/u/2109897583技术博客:http://home.cnblogs.com/u/webARM/



【今日微信公号推荐↓】

更多推荐请看值得关注的技术和设计公众号


其中推荐了包括技术设计极客 和 IT相亲相关的热门公众号。技术涵盖:Python、Web前端、Java、安卓、iOS、PHP、C/C++、.NET、Linux、数据库、运维、大数据、算法、IT职场等。点击《值得关注的技术和设计公众号》,发现精彩!


 
前端大全 更多文章 详解Javascript中的Object对象 结合个人经历总结的前端入门方法 前端不为人知的一面–前端冷知识集锦 一份优秀的前端开发工程师简历是怎么样的? 浅谈Web缓存
猜您喜欢 编程能力与编程年龄 做软件项目,程序员如何避免踩坑? 一致哈希 平安金融科技移动技术周报(第三十一期) 你参加华为网院杯考试,你了解博赛网络么?