瀏覽器中實(shí)現(xiàn)JavaScript計(jì)時(shí)器的4種創(chuàng)新方式
在 Web Worker中使用無限同步循環(huán)
由于 Web Worker 本質(zhì)上是Web線程,因此你可以在其中無限循環(huán)而不阻塞主線程。這使你可以訪問微秒級的時(shí)間分辨率。這對于在 Worker 中做出時(shí)間關(guān)鍵的決策是特別實(shí)用的,可以讓主線程準(zhǔn)確的知道什么時(shí)候合適。例如:只要微秒是質(zhì)數(shù),就渲染某些東西。要訪問微秒,你可以使用 performance.now。
優(yōu)點(diǎn)
- 微秒級分辨率。
 - UI線程的成本幾乎為零。
 - 利用 Web Workers 的消息傳遞設(shè)計(jì),從UI線程角度完全異步。
 - 安全結(jié)束,與 setInterval 不同,調(diào)用 worker.terminate 保證不會(huì)再收到任何消息。
 
引用MDN:“ Worker 的 Terminate() 方法立即終止 Worker。它不會(huì)為等待 Worker 完成里面執(zhí)行的程序,而是會(huì)立即停止。”
缺點(diǎn)
- 即使你可以做出毫秒級的決策,但返回UI線程的消息傳遞也是異步的。你無法像在 Worker 中做出決定那樣及時(shí)渲染。
 - 保持線程完全被占用。手機(jī)電池可能會(huì)好點(diǎn)很快。
 - 需要 Web Worker 支持。
 - 選項(xiàng)卡未聚焦時(shí)不會(huì)暫停。
 
使用CSS動(dòng)畫處理時(shí)間事件(animationiteration)
如果創(chuàng)建帶有無限動(dòng)畫的 div。你可以訂閱其 animationiteration 事件,并在事件 animation-duration 回調(diào)時(shí)得到通知。
優(yōu)點(diǎn)
- 自動(dòng)暫停時(shí),標(biāo)簽不在焦點(diǎn)。當(dāng)標(biāo)簽不在焦點(diǎn)上時(shí),事件根本不會(huì)觸發(fā)。無需擔(dān)心調(diào)用時(shí)卡住,這些調(diào)用將在再次顯示選項(xiàng)卡時(shí)立即運(yùn)行。
 - 從 DOM 中刪除隱藏的 div 時(shí),將自動(dòng)進(jìn)行清理。例如,如果你有一個(gè)可渲染時(shí)間的 React 組件,則無需在卸載時(shí)做任何事情。該 div 將被刪除,該事件將不再觸發(fā)。
 - 調(diào)用邏輯很優(yōu)雅:.addEventListener("animationiteration", fun)。
 - 超級干凈的方法來延遲啟動(dòng)計(jì)時(shí)器:animation-delay。
 
缺點(diǎn)
- 有點(diǎn)太聰明了,可能會(huì)使你的協(xié)作者感到困惑。
 - 取決于 DOM 和 CSSOM 。其他CSS規(guī)則可能會(huì)干擾你的規(guī)則。這就是為什么我建議創(chuàng)建一個(gè)像這樣的任意不存在的標(biāo)記的原因  
。也許用CSS動(dòng)畫代碼整齊地放入其中創(chuàng)建自定義元素?。  - 如果元素具有 display: none; 屬性,則無效。
 
使用SVG 標(biāo)簽(SMIL動(dòng)畫)
- <svg>
 - <rect>
 - <animate
 - attributeName="rx"
 - values="0;1"
 - dur="1s"
 - repeatCount="indefinite"
 - />
 - </rect>
 - </svg>
 
如果這樣調(diào)用:animate.addEventListener('repeat', fun),你的函數(shù)將每秒被調(diào)用一次。
優(yōu)點(diǎn)
- 即使 SVG 為 display: none;也會(huì)生效。
 - 從 DOM 中刪除 SVG 時(shí)自動(dòng)停止。
 - 直到整頁加載才開始渲染。
 - 選項(xiàng)卡聚焦時(shí)自動(dòng)暫停。
 
缺點(diǎn)
- 有點(diǎn)太聰明了,可能會(huì)使你的協(xié)作者感到困惑。
 - 取決于 DOM 和 CSSOM 。與上述相同的警告。其他CSS規(guī)則可能會(huì)干擾你的配置。
 - IE 和 Edge (在 Chromium 之前)不受支持。
 - 不準(zhǔn)確 根據(jù)我的測試,它可能會(huì)延遲15ms。
 - 直到整頁加載才開始。是的,可能是一個(gè)缺點(diǎn),但是也是一個(gè)功能。
 
使用 Web Animations API
Web Animations API 允許你在 JavaScript 中為 DOM 元素設(shè)置動(dòng)畫。
有趣的是,你可以使未渲染完的元素具有動(dòng)畫效果!這使你能夠訪問純 JS (和 Web api)中的定時(shí)機(jī)制。
這是替代 setTimeout 的實(shí)現(xiàn):
- function ownSetTimeout(callback, duration) {
 - const div = document.createElement('div');
 - const keyframes = new KeyframeEffect(div, [], { duration, iterations: 1 });
 - const animation = new Animation(
 - keyframes,
 - document.timeline
 - );
 - animation.play();
 - animation.addEventListener('finish', () => {
 - callback();
 - });
 - }
 
很整潔,不是嗎?
優(yōu)點(diǎn)
- 不需要DOM交互。
 - 不熟悉的人容易理解。
 - 標(biāo)簽未聚焦時(shí)自動(dòng)暫停。
 
缺點(diǎn)
- 仍然是一個(gè)建議。不要在生產(chǎn)中使用。
 - 可怕的兼容性??赡軆H適用于 Chromium。
 - 還是有點(diǎn)違反直覺的。
 - 標(biāo)簽未聚焦時(shí)暫停。如果用作 setTimeout 的替代品可能會(huì)很糟糕。
 - 不能間隔使用。僅 onfinish 活動(dòng)可用。
 - 不準(zhǔn)確 根據(jù)我的測試,誤差 ±5ms。
 


















 
 
 

 
 
 
 