摘要:前端網(wǎng)頁倒計時是非常常見的應用,我們在各大購物網(wǎng)站的秒殺活動中總是能見到它的身影。這個方法簡單但也有點粗暴,下面提供一種方法,能夠一定程度上不依賴服務(wù)端實現(xiàn)倒計時的糾偏。
前端網(wǎng)頁倒計時是非常常見的應用,我們在各大購物網(wǎng)站的秒殺活動中總是能見到它的身影。但是在實際情況中,我們常常會發(fā)現(xiàn)當網(wǎng)頁不刷新、讓倒計時程序持續(xù)運行時,顯示時間相比實際時間會越來越慢,相信大家也有在秒殺時間即將到來時不停刷新頁面的經(jīng)歷。原因自然也不難理解:倒計時通常使用定時器(setTimeout 或者 setInterval )實現(xiàn),而 JavaScript 的單線程特性使得主線程執(zhí)行棧中出現(xiàn)阻塞時,任務(wù)隊列中的異步任務(wù)并不能及時執(zhí)行,因此瀏覽器并不能保證在定時器設(shè)置的時間結(jié)束后代碼總是被準時執(zhí)行,這就造成了倒計時的偏差。
一般的解決方法是前端定時向服務(wù)器發(fā)送請求獲取最新的時間差來校準倒計時時間,主動(程序里設(shè)置定時請求)或被動的(F5 已被用戶按壞)區(qū)別而已。這個方法簡單但也有點粗暴,下面提供一種方法,能夠一定程度上不依賴服務(wù)端實現(xiàn)倒計時的糾偏。代碼非原創(chuàng),時間久遠忘了出處,在此記錄一下學習過程以免遺忘。如有侵權(quán)請聯(lián)系我。
首先我們需要模擬主線程阻塞的環(huán)境,同時又不能讓主線程一直阻塞:
setInterval(function(){ let j = 0 while(j++ < 100000000) }, 0)
然后是主要的代碼:
const interval = 1000 let ms = 50000, // 從服務(wù)器和活動開始時間計算出的時間差,這里測試用 50000 ms let count = 0 const startTime = new Date().getTime() let timeCounter if( ms >= 0) { timeCounter = setTimeout(countDownStart, interval) } function countDownStart () { count++ const offset = new Date().getTime() - (startTime + count * interval) // A let nextTime = interval - offset if (nextTime < 0) { nextTime = 0 } ms -= interval console.log(`誤差:${offset} ms,下一次執(zhí)行:${nextTime} ms 后,離活動開始還有:${ms} ms`) if (ms < 0) { clearTimeout(timeCounter) } else { timeCounter = setTimeout(countDownStart, nextTime) } }
代碼的基本原理并不復雜:通過遞歸調(diào)用 setTimeout 進行倒計時操作的執(zhí)行。而每次執(zhí)行函數(shù)時會維護一個 count 變量,用以記錄已經(jīng)執(zhí)行過的倒計時次數(shù),使用代碼 A 處的公式可計算出當前執(zhí)行倒計時的時間與實際應執(zhí)行時間的偏差,進而可以計算出下次執(zhí)行倒計時的時間。
本文首發(fā)于我的博客(點此查看),歡迎關(guān)注。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98042.html
摘要:由于引擎同一時間只執(zhí)行一段代碼這是由單線程的性質(zhì)決定的,所以每個代碼塊阻塞了其它異步事件的進行。這意味著瀏覽器將等待著一個新的異步事件發(fā)生。異步的任務(wù)執(zhí)行的順序是不固定的,主要看返回的速度。 我們經(jīng)常說JS是單線程的,比如node.js研討會上大家都說JS的特色之一是單線程的,這樣使JS更簡單明了,可是大家真的理解所謂JS的單線程機制嗎?單線程時,基于事件的異步機制又該當如何,這些知識...
摘要:注意客戶端與服務(wù)器日期進行傳輸?shù)臅r候一般都是用大整數(shù)時間戳進行傳輸。 前言 一個網(wǎng)站的開發(fā)需要要UI、前端、后端三種工程師?,F(xiàn)在的企業(yè)在招聘前端工程師的時候一般都要求其了解或者掌握一些后端的知識。因此,此文章主要介紹javascript的日期類型,也粗略的介紹一下php的日期類型,以及二者是如何交互數(shù)據(jù)的。 時間戳 什么是時間戳 時間戳是從格林威治時間1970年1月1日(00:0...
摘要:注意客戶端與服務(wù)器日期進行傳輸?shù)臅r候一般都是用大整數(shù)時間戳進行傳輸。 前言 一個網(wǎng)站的開發(fā)需要要UI、前端、后端三種工程師?,F(xiàn)在的企業(yè)在招聘前端工程師的時候一般都要求其了解或者掌握一些后端的知識。因此,此文章主要介紹javascript的日期類型,也粗略的介紹一下php的日期類型,以及二者是如何交互數(shù)據(jù)的。 時間戳 什么是時間戳 時間戳是從格林威治時間1970年1月1日(00:0...
摘要:案例每隔毫秒調(diào)用函數(shù)并顯示時間。當點擊按鈕時,停止時間代碼如下計時器每隔毫秒調(diào)用函數(shù),并將返回值賦值給計時器計時器,在載入后延遲指定時間后去執(zhí)行一次表達式僅執(zhí)行一次。該值標識要取消的延遲執(zhí)行代碼塊。 簡述 本系列將持續(xù)更新Javascript基礎(chǔ)部分的知識,誰都想掌握高端大氣的技術(shù),但是我覺得沒有一個扎實的基礎(chǔ),我認為一切高階技術(shù)對我來講都是過眼云煙,要成為一名及格的前端工程師,必須把...
摘要:網(wǎng)上有很多前端的學習路徑文章,大多是知識點羅列為主或是資料的匯總,數(shù)據(jù)量讓新人望而卻步。天了解一個前端框架。也可以關(guān)注微信公眾號曉舟報告,發(fā)送獲取資料,就能收到下載密碼,網(wǎng)盤地址在最下方,獲取教程和案例的資料。 前言 好的學習方法可以事半功倍,好的學習路徑可以指明前進方向。這篇文章不僅要寫學習路徑,還要寫學習方法,還要發(fā)資料,干貨滿滿,準備接招。 網(wǎng)上有很多前端的學習路徑文章,大多是知...
閱讀 3364·2021-11-11 16:54
閱讀 3523·2021-10-11 10:58
閱讀 1262·2021-08-30 09:41
閱讀 1808·2019-08-30 15:54
閱讀 2032·2019-08-30 14:00
閱讀 2706·2019-08-29 17:13
閱讀 1672·2019-08-29 15:19
閱讀 613·2019-08-29 15:14