<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【每日一題】倒計時實現(xiàn)如何解決時間偏差?

          共 2806字,需瀏覽 6分鐘

           ·

          2021-09-17 19:44

          人生苦短,總需要一點儀式感。比如學(xué)前端~




          setTimeout/setInterval 實現(xiàn)倒計時如何解決時間偏差?

          造成時間誤差的原因

          在前端實現(xiàn)中一般會通過 setTimeoutsetInterval 方法實現(xiàn)一個倒計時效果。但是使用這些方法會存在時間偏差的問題,這是由于 js 的程序執(zhí)行機制造成的。setTimeout 和 setInterval 的作用是隔一段時間將回調(diào)事件加入到事件隊列中,由于JS的事件循環(huán)機制限制,加入到事件隊列中的回調(diào)函數(shù)并不是立即執(zhí)行的,它會等到當前執(zhí)行棧為空的時候再被取出并執(zhí)行。因此,事件函數(shù)等待執(zhí)行的時間就是造成定時器時間誤差的原因。

          解決倒計時中的誤差有兩種辦法:

          • 第一種就是通過前端定時向服務(wù)器發(fā)送請求獲取最新的時間差,以此來校準倒計時時間。但是這樣會存在一個很大的問題,就是每隔一秒去請求服務(wù)器,這樣如果用戶多了,服務(wù)器就會奔潰---內(nèi)存占用率很大
          • 第二種方式是前端根據(jù)偏差時間來自動調(diào)整間隔時間的方式來實現(xiàn)的。這一方式首先是以 setTimeout 遞歸的方式來實現(xiàn)倒計時,然后通過一個變量來記錄已經(jīng)倒計時的秒數(shù)。每一次函數(shù)調(diào)用的時候,每次都將變量+1,然后根據(jù)這個變量和每次的間隔時間,我們就可以計算出此時無偏差時應(yīng)該顯示的時間。然后將當前的真實時間與這個時間相減,這樣我們就可以得到時間的偏差大小,因此我們在設(shè)置下一個定時器的間隔大小的時候,我們就從間隔時間中減去這個偏差大小,以此來糾正由于程序執(zhí)行所造成的時間誤差。

          const interval = 1000;
          // 從服務(wù)器和活動開始時間計算出的時間差,這里測試用 50000 ms
          let ms = 50000;
          let count = 0//記錄次數(shù)
          const startTime = new Date().getTime(); //開始時間
          let timeCounter;
          if (ms >= 0) {
            timerCounter = setTimeout(countDownStart, interval); //返回一個對象
          }
          function countDownStart({
            count++;
            const offset = new Date().getTime() - (startTime + count * interval); //剩余的時間
            let nextInterval = interval - offset;
            if (nextInterval < 0) {
              nextInterval = 0;
            }
            ms -= interval;
            console.log(
              `誤差:${offset} ms,下一次執(zhí)行:${nextInterval} ms 后,離活動開始還有:${ms} ms`
            );
            if (ms < 0) {
              clearTimeout(timeCounter); //銷毀定時器
            } else {
              timeCounter = setTimeout(countDownStart, nextInterval); //重開一個定時器
            }
          }

          執(zhí)行結(jié)果圖

          可以看到,當延遲了2ms調(diào)用函數(shù)后,下次間隔會變成1000 - 2 = 998ms

          代碼圖解




          所有《每日一題》的 知識大綱索引腦圖 整理在此:
          https://www.yuque.com/dfe_evernote/interview/everyday


          END
          愿你歷盡千帆,歸來仍是少年。


          讓我們一起攜手同走前端路!

          關(guān)注公眾號回復(fù)【加群】即可

          瀏覽 124
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  午夜精品理论 | 草久97在线视频免费观 | 亚洲人成人网站色 | 国产AAA片 | 乱论理论激情亚州欧美 |