<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    于吉吉的技術博客

    建造高性能門戶網

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      65 隨筆 :: 6 文章 :: 149 評論 :: 0 Trackbacks

    前段時間做了一個團購秒殺倒計時的js展現的例子(http://m.tkk7.com/dongbule/archive/2011/12/06/365687.html),倒計時的方式主要使用setTimeout的函數進行遞歸實現,由于是使用setTimeout,所以根據js的引擎,這其中將可能存在一定的時間誤差,一個誤差不要緊,兩個誤差無所謂,但長時間的誤差堆積將出現較大的偏離值,所以根據秒殺倒計時的例子,做了一個簡單的模擬的誤差堆積測試,并在各個瀏覽器中進行測試。
    鑒于秒殺倒計時都是以一秒為單位,所以下面的例子也都以1000毫秒為計算,當然各個瀏覽器的實現和附加代碼的編寫也會造成一定的時間誤差,這部分誤差也合并在setTimeout的實現里面計算誤差。

    <div id="show" style="width:500px;"></div>
    <script>
    var w = 1000;
    var second = 0;
    function showtime(){    
    showtime.curr
    =  +new Date();    
    setTimeout('showtime()',
    1000);    
    document.getElementById(
    "show").innerHTML+=second +"    "+(showtime.curr-(showtime.last||showtime.curr)-1000)+"    <br/>";    
    showtime.last
    =showtime.curr;    
    second
    ++;
    }
    showtime();
    </script>

    可以看到在各個不同的瀏覽器在不同的秒數中出現不同的誤差,當然這個跟我本機的瀏覽器和環境有關



    下面再將這些誤差值進行疊加測試

    <div>
    <div id="show" style="width:500px;"></div>
    </div>
    <script>
    var w = 1000;
    var i = 0;
    function showtime(){
        showtime.curr
    =  +new Date();
        f 
    = setTimeout('showtime()',1000);
        w
    +=(showtime.curr-(showtime.last||showtime.curr)-1000);
        document.getElementById(
    "show").innerHTML+=i+"   "+(showtime.curr-(showtime.last||showtime.curr)-1000)  +"    "+w+" 

    <br/>
    ";
        showtime.last
    =showtime.curr;
        i
    ++;
    }
    showtime();
    </script>



    IE和chrome相對較為穩定,不知道是不是我本機環境的原因,firefox出現了很多大偏差,可以選擇定時清空這個誤差值來處理,或是采用鏈式的setTimeOut()來處理。

    <div id="show" style="width:300px;"></div>
    <script>
    var w = 1000;
    var i = 0;
    var f ;
    var t ;
    var k = 0;
    function showtime(){
        showtime.curr
    =  +new Date();
        f 
    = setTimeout('showtime()',1000);
        w
    +=(showtime.curr-(showtime.last||showtime.curr)-1000);
        document.getElementById(
    "show").innerHTML+=i+"   "+w+"  "+(showtime.curr-(showtime.last||showtime.curr)-1000)  +"    <br/>";
        showtime.last
    =showtime.curr;
        i
    ++;
    }
    function round(){
        
    if(k!=0){
            clearTimeout(f);
            showtime();
            document.getElementById(
    "show").innerHTML+="  clear<br/>";
            w
    =0;
        }
        setTimeout('round()',
    10000);
        k
    ++;
    }
    showtime();
    round();
    </script>

    其實為什么javascript的定時器會出現所謂的不可靠或偏差的情況,這是可以理解的,最主要的問題是它們并不是所謂的線程,其實
    javascript是運行于單線程的環境中,而定時器只是計劃代碼在未來某個執行的時間,執行的時間點是不能被保證的,因為在頁面的生命周期中,不同時間可能存在其他代碼,或各個瀏覽器的內核控制住javascript進程。

    settimeout幾個見解
    1、setTimeOut  !=  thread | 時間片的并發調用
    2、javascript以單線程的方式運行于瀏覽器的javascript引擎中
    3、setTimeout 只是把要執行的代碼在設定的時間點插入js引擎維護的代碼隊列
    4、setTimeout 插入代碼隊列并不意味著代碼就會立馬執行的

    function showtime(){
    // code 1...
    f = setTimeout('showtime()',200);     //200毫秒后要插入執行代碼對瀏覽器的js隊列
    // code 2...
    }
    以上面面的代碼為例,說說它的執行流程
    Code 1 -> 200毫秒后通知瀏覽器有隊列插入   ->   Code 2   ->   showtime()  ->    …
    這個種重復遞歸可能會造成2個問題:
    1 . 時間間隔可能小于定時調用的代碼的執行時間
    2 . 時間間隔或許會跳過

    時間間隔或許會跳過


    5ms : code1 代碼執行完畢,200ms后有定時器進入隊列
    205ms : 定時器進入隊列,code2繼續
    300ms : function代碼結束,定時器從隊列中取出,執行
    405ms : 第二個定時器進入隊列,第一個定時器的代碼在執行中
    605ms : 第三個定時器意圖進入隊列失敗,這個點的settimeout丟失

    為了避免這2個問題,可以采用鏈式setTimeOut()進行調用
    setTimeOut(function(){
    code處理...
    setTimeOut(arguments.callee,interval);
    },interval);
    這個模式鏈式條用setTimeOut(),每次函數執行的時候都會創建一個新的定時器,第二個setTimeOut調用使用了arguments.callee來獲取當前執行的函數引用,并為其設置另外一個定時器,這樣的好處在于,在前一個定時器執行完之前不會向隊列中插入新的定時器代碼,確保不會有任何的確實間隔,而且它可以保證在下一次定時器代碼執行前,至少等待指定的間隔,避免連續的運行。



    //-------------//
    秒殺的定時器已經通過檢測正式運行了,博客記錄得不好,表達不是很清楚,關于setTimeOut的函數主要參考了《JavaScript高級程序設計(第2版)》的第18章。
    posted on 2012-01-10 15:15 陳于喆 閱讀(3547) 評論(6)  編輯  收藏 所屬分類: web開發

    評論

    # re: 對setTimeout的誤差堆積測試和簡單分析 2012-01-10 23:00 rox
    這個夠專業,學習一下!  回復  更多評論
      

    # re: 對setTimeout的誤差堆積測試和簡單分析 2012-01-11 09:06 tb
    很專業啊   回復  更多評論
      

    # re: 對setTimeout的誤差堆積測試和簡單分析 2012-01-11 09:20 HiMagic!
    這個在我的博客也提到過,當頁面內容較多時偏差更嚴重。如果只靠setTimeout的interval倒計時,而不看本地Date當前值,相差更嚴重。  回復  更多評論
      

    # re: 對setTimeout的誤差堆積測試和簡單分析 2012-01-12 15:17 第一時尚網
    學習了。。。謝謝博主  回復  更多評論
      

    # re: 對setTimeout的誤差堆積測試和簡單分析 2013-09-27 20:47 購物導航
    購物導航http://www.5a77.com/
    不好意思呵,來推廣一下自己的網站
    也支持一下你的文章,寫得這么好,剛好路過呵  回復  更多評論
      

    # re: 對setTimeout的誤差堆積測試和簡單分析 2015-08-11 14:36 hirain
    代碼中: showtime.curr= +new Date();是什么意思,為什么要寫個加號?  回復  更多評論
      

    主站蜘蛛池模板: 亚洲第一页日韩专区| 成人黄页网站免费观看大全| 区久久AAA片69亚洲| 免费人成在线观看播放a| 国产精品久免费的黄网站| 亚洲av纯肉无码精品动漫| 日本免费一区二区三区最新vr| 国产精品国产亚洲区艳妇糸列短篇 | 亚洲AV色欲色欲WWW| 日韩人妻无码免费视频一区二区三区| 精品日韩99亚洲的在线发布| 无人影院手机版在线观看免费| 国产午夜亚洲精品| 四虎1515hm免费国产| 美女啪啪网站又黄又免费| 亚洲av无码成人精品区| 成年免费a级毛片免费看无码| 亚洲AV成人无码久久精品老人| 久久午夜伦鲁片免费无码| 亚洲成aⅴ人片在线观| 久久精品a一国产成人免费网站| 亚洲欧美乱色情图片| 亚洲国产精品国产自在在线| 91成人免费福利网站在线| 亚洲黄色网站视频| 永久黄网站色视频免费直播| 日韩精品无码永久免费网站| 久久精品国产亚洲av麻| 大地资源免费更新在线播放| 真人无码作爱免费视频| 亚洲国产精品VA在线观看麻豆 | 亚洲精品视频免费在线观看| 成人亚洲国产va天堂| 亚洲精品无码成人片在线观看| 日本免费高清视频| 亚洲国产成人精品无码区花野真一| 亚洲一级片内射网站在线观看| 19禁啪啪无遮挡免费网站| 免费精品国自产拍在线播放| 亚洲天堂一区二区| 免费人成视网站在线观看不卡|