JS利用闭包自制的沙漏类

Posted 码出世界

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS利用闭包自制的沙漏类相关的知识,希望对你有一定的参考价值。

【需求】

某应用有一耗时任务,目的是取出一批员工数据显示在页面上,但由于奇特的网络环境,每次调用都要数秒,客户要求在页面上动态显示耗时。

【坑】

动态显示耗时,多会用spanId,setInterval(funciton,mseconds),clearInterval(handler),startTime等一套五六个全局变量和函数。如果需要动态显示耗时的地方不止一处,那么区别和维护一堆全局变量和函数必是费力不讨好的事。

【解决方案】

必须用JS类实现,把要显示事件的SpanId,启动时间和句柄三个变量,启动、显示、停止三个动作都归纳到类里去。

【后台耗时和取数的模拟实现】

@RestController
public class MockRestCtrl extends Pager
    
    @RequestMapping(value="/fetchEmps", method=RequestMethod.GET)
    public Map<String,Object> fetchEmps(int waitSeconds)
        try 
            Thread.sleep(waitSeconds*1000);
        catch(Exception ex) 
            //
        
        
        Map<String,Object> retvalMap=new LinkedHashMap<String,Object>();
        List<Emp> datas=new ArrayList<Emp>();
        datas.add(new Emp(1,"Andy",24));
        datas.add(new Emp(3,"Bill",34));
        datas.add(new Emp(4,"Cindy",44));
        datas.add(new Emp(5,"Douglas",54));
        datas.add(new Emp(9,"Eliot",64));
        
        retvalMap.put("datas", datas);
        
        return retvalMap;
    

上面代码使用了SpringBoot的RestController来实现后台,响应函数接受waitSecond参数,然后用Thread.sleep歇数秒,之后再造数据送回。

有了这样的后台,前台送入不同的waitSeconds就能实现有差别的耗时。

【沙漏类的实现】(本文重点)

function Sandglass()
    var spanId;
    var handler;
    var startTime;

    this.setSpanId=function(id)
        spanId=id;
    

    this.start=function(time)
        startTime=time;
        handler=setInterval(this.showElapsed,500);
    

    this.showElapsed=function()
        var now=new Date();

        var diff=(now-startTime)/1000;
        var d=parseInt(diff/86400);
        var h=parseInt(diff/3600)-24*d;
        var m=parseInt((diff % 3600) / 60);
        var s=parseInt(diff % 60);
        var elapsed=d+"day "+h+"hour "+m+"minute "+s+"second";

        document.getElementById(spanId).innerText=" 已耗时:"+elapsed;
    

    this.stop=function()
        clearInterval(handler);
    

以上代码利用闭包实现了私有成员,这些成员只能被函数中定义的函数使用。下面我们可以看看对于使用者来说这个类该怎么用:

【沙漏的初始化】

var sandglass1=new Sandglass();
sandglass1.setSpanId("span1");

【沙漏的启动】

sandglass1.start(new Date());

【沙漏的停止】

sandglass1.stop();

从以上代码可以看出,使用者能用的方法少而简单,较难出错。Sandglass相对复杂的细节把控在了作者手中。

【实现效果】

 【前台HTML代码】

<table>
    <tr>
        <td width=50%>
            <table border="1" class="table">
                <caption>Table1<span id="span1"></span></caption>
                <thead>
                    <tr>
                        <td width="120px">id</td>
                        <td width="120px">Name</td>
                        <td width="120px">Age</td>
                    </tr>
                </thead>
                <tbody id="table1">
                </tbody>
            </table>
        </td>
        <td width=50%>
            <table border="1" class="table">
                <caption>Table2<span id="span2"></span></caption>
                <thead>
                    <tr>
                        <td width="120px">id</td>
                        <td width="120px">Name</td>
                        <td width="120px">Age</td>
                    </tr>
                </thead>
                <tbody id="table2">
                </tbody>
            </table>
        </td>
    </tr>
</table>

【前台JS代码】

<script type="text/javascript">
    
    var sandglass1=new Sandglass();
    sandglass1.setSpanId("span1");
    
    var sandglass2=new Sandglass();
    sandglass2.setSpanId("span2");
    
    fillTable(\'table1\',3,sandglass1);
    fillTable(\'table2\',5,sandglass2);

    function fillTable(tableId,waitSeconds,sandglass)
        sandglass.start(new Date());
    
        $.ajax(
            url:"/mediacool/fetchEmps",
            data:waitSeconds:waitSeconds,
            type:"get",
            dataType:"json",
            timeout:50000,
            error:function(xhr,textStatus,errorThrown)alert(\'ajax error\'),
            success:function(rsps)
                sandglass.stop();
                showDatasInTable(rsps.datas,tableId);
            ,
        );
    
    
    function showDatasInTable(datas,tableId)
        
        var table=document.getElementById(tableId);

        // remove remained rows
        var trs=table.childNodes;
        for(var i=trs.length-1;i>=0;i--)
            table.removeChild(trs[i]);
        

        // add new rows    
        for(var i=0,n=datas.length;i<n;i++)
            var data=datas[i];
            
            var td1=document.createElement("td");
            td1.appendChild(document.createTextNode(data.id));
            
            var td2=document.createElement("td");
            td2.appendChild(document.createTextNode(data.name));
            
            var td3=document.createElement("td");
            td3.appendChild(document.createTextNode(data.age));

            var tr=document.createElement("tr");
            tr.appendChild(td1);
            tr.appendChild(td2);
            tr.appendChild(td3);
            
            if(i % 2==0)
                tr.style.backgroundColor="#f5f2eb";
            
            
            table.appendChild(tr);
        
    
    
    function Sandglass()
        var spanId;
        var handler;
        var startTime;

        this.setSpanId=function(id)
            spanId=id;
        

        this.start=function(time)
            startTime=time;
            handler=setInterval(this.showElapsed,500);
        

        this.showElapsed=function()
            var now=new Date();

            var diff=(now-startTime)/1000;
            var d=parseInt(diff/86400);
            var h=parseInt(diff/3600)-24*d;
            var m=parseInt((diff % 3600) / 60);
            var s=parseInt(diff % 60);
            var elapsed=d+"day "+h+"hour "+m+"minute "+s+"second";

            document.getElementById(spanId).innerText=" 已耗时:"+elapsed;
        

        this.stop=function()
            clearInterval(handler);
        
    
</script>

 

END

以上是关于JS利用闭包自制的沙漏类的主要内容,如果未能解决你的问题,请参考以下文章

AJAX相关JS代码片段和部分浏览器模型

js代码如何封装

js利用闭包封装自定义模块的几种方法

用JS自制表格软件玩数据9. 自制三维 K线图 蜡烛图

用JS自制表格软件玩数据9. 自制三维 K线图 蜡烛图

用JS自制表格软件玩数据4. 行列计数器的实现