休息提醒的準確度,取決於計時器是將目前的時鐘時間與儲存的截止時間做比較,而不是在每次刻度時從計數器中減去一秒鐘;這就是為什麼被暫停、被節流,或從睡眠中喚醒的分頁,在恢復時仍會回報正確的階段。這個詞組一次涵蓋了三件具體的事:視覺倒數顯示與休息實際應該出現的時刻有多接近、排程在長時間暫停後是否能追上、以及顯示的剩餘時間是否與底層的截止時間一致。兩個使用相同分鐘與秒數輸入的計時器,如果一個圍繞遞減計數器建構、另一個圍繞截止時間運算建構,兩者的結果可能相差好幾分鐘。一個總是顯示「還剩十六分鐘」但實際截止時間已經過了十二分鐘的排程,雖然顯示上是準確的,但事實上是錯誤的;一個在喚醒後短暫顯示相同數字、然後跳到真正階段的排程,雖然乍看之下令人擔憂,但事實上是正確的。了解你的工具採用哪種行為,是信任提醒的基礎,尤其在桌面工作、閱讀、讀書,或任何一個錯過或遲到的休息會悄悄改變當天節奏的工作中更是如此。

break reminder accuracy
休息提醒的準確度

「休息提醒的準確度」實際涵蓋了什麼

這個詞組可以拆解為讀者想問的三個具體問題。第一個是視覺精確度:螢幕上的倒數是否以秒為單位平滑變化,還是會跳動或停滯?第二個是階段正確性:在休息應該開始時,網頁是否準時切換狀態,還是卡在工作標籤上不動?第三個是恢復後的行為:如果分頁曾經睡眠、被節流或被隱藏,排程是否會先走過每一個完整經過的工作與休息階段,再顯示目前的階段,還是會一直顯示舊的剩餘值?一項工具可能在某個維度表現很好,但在另一個維度表現很差。一個顯示平滑、次秒級倒數的計時器,但在長時間暫停期間可能會嚴重漂移。一個使用截止時間運算的計時器在喚醒後可能會短暫顯示一個大跳躍,然後才穩定在正確的階段上。了解你的工具做出哪種取捨,是信任休息提醒與忽略提示之間的差異。

為何一般倒數計時器在分頁暫停期間會失去時間

大多數看似準確的瀏覽器計時器,都是以每次 setInterval 回呼(通常是每 1000 毫秒)將剩餘秒數遞減的方式實作成倒數計時器。當分頁處於前景時,這種做法沒問題:每次刻度減去一秒鐘,顯示內容與實際情況的誤差在一秒鐘以內。一旦分頁被隱藏,作業系統可能將間隔節流為每秒一次或每分鐘一次,瀏覽器在裝置睡眠時可能會完全暫停計時器,而當筆電上蓋闔上時,JavaScript 可能會停止執行。當分頁被喚醒時,計數器會從最後一次刻度時儲存的值恢復,而不是從時鐘時間所要求的值恢復。如果分頁在工作階段的 50 分鐘期間睡眠了 10 分鐘,顯示的剩餘時間仍會聲稱還有大約 40 分鐘,但真實時間已經將排程推進到休息階段。結果就是提醒晚了 10 分鐘才響起,對於桌面工作或讀書來說,這可能會悄悄改變當天後續每一次休息的時間點,侵蝕使用者原本以為自己設定好的節奏。

以截止時間為基礎的排程如何修正休息提醒的準確度

以截止時間為基礎的排程透過儲存一個絕對的毫秒時間戳,而不是剩餘秒數計數器,來避免整個類別的錯誤。每次視覺更新都會將目前的時鐘時間 Date.now() 與儲存的截止時間做比較,並根據已經過的時間渲染出對應的階段。如果一個工作加休息的循環為 3,030 秒,透過排程開始以來總經過時間的商數與餘數計算,可以在固定的時間內找到目前的階段,即使瀏覽器在暫停期間跳過了許多秒或許多分鐘也是如此。當分頁在長時間節流後被喚醒時,排程不需要重播錯過的回呼;它只需要讀取時鐘時間並顯示正確的階段。250 毫秒的顯示更新頻率讓螢幕上的倒數保持靈敏,但不會宣稱任何提醒具有次秒級的精確度。這就是 Break Reminder 所使用的機制,這也是為什麼網頁會顯示距離下一次休息的時間、在截止時間到達時切換到可見的休息狀態、計算已開始的休息次數,並在休息結束後排定下一個工作區間。

行為倒數遞減計時器截止時間運算計時器
分頁處於前景時的視覺倒數平滑,誤差約 ±1 秒平滑,誤差約 ±1 秒
分頁睡眠 10 分鐘後顯示舊的剩餘值;下一次休息延遲響起走過每一個已經過的階段;目前的階段在下次回呼時出現
上蓋闔上的筆電喚醒後可能無限期地顯示過期的剩餘值一旦執行恢復,階段與剩餘時間立即與時鐘時間一致
排程執行期間編輯輸入的影響容易悄悄改變目前有效的截止時間輸入欄位已停用;目前截止時間的意義無法改變
顯示更新頻率通常為每秒一次每 250 毫秒一次
錯過的視覺提示在使用者不知情的情況下靜默計算會明確揭露;只有當階段實際觸發執行時,休息次數才會遞增

設定一個具備可靠計時功能的休息提醒

請依照下列步驟,在目前分頁中啟動一個準確的排程。提醒完全存在於開啟的網頁上,因此你放置它的位置與你選擇的值同樣重要。

  1. 在進行工作的分頁中開啟 Break Reminder,讓排程與可見的倒數與活動保持一致。
  2. 輸入一個介於 1 到 180 分鐘之間的整數提醒間隔,以配合工作的步調;較長的間隔適合閱讀與深度專注,較短的間隔適合重複性的桌面工作。
  3. 輸入一個介於 10 到 600 秒之間的整數休息長度。600 秒(10 分鐘)的上限相當寬鬆,足夠伸展或裝杯水,而不會讓提醒變成一個工作階段計時器。
  4. 選擇「Start reminder」(開始提醒)。網頁現在會儲存一個以毫秒為單位的絕對截止時間,並在每次更新時將其與時鐘時間做比較。
  5. 在計時重要的時候保持分頁開啟且可見;被節流的背景分頁與鎖定的裝置可能會延遲視覺更新。
  6. 如果你提早到達一個自然的停止點,請選擇「Take a break now」(立即休息)以立即翻轉目前的階段,並保留已開始的休息次數。
  7. 當暫停結束時,選擇「Resume work」(恢復工作)以從目前的時鐘時間開始一個全新的工作截止時間,或在編輯這兩個持續時間之前重設排程。

手動控制項與網頁上的倒數

網頁上的倒數使用進位的方式將時間格式化為下一次階段變更的時間,因此即使剩餘值為 0.4 秒,在通過階段邊界之前仍會顯示為 1 秒。在工作階段期間,顯示器會倒數到下一次休息;在休息期間,則會倒數到下一個工作區段。每一次已開始的休息都會被計算在內,因此排程可以顯示當天已經產生的休息次數,而不會宣稱使用者真的有休息。「Take a break now」控制項會從目前的時鐘時間建立一個新的截止時間,「Resume work」則以相反方向執行同樣的操作,而「Reset」會清除目前有效的排程,而不會動到兩個輸入欄位。由於輸入欄位在排程執行期間是停用的,因此目前截止時間的意義無法在循環中途悄悄改變;如果需要新的持續時間,請先重設、編輯數值,然後再次啟動。無效的小數、零、負值,以及超出 1–180 分鐘或 10–600 秒範圍的值,都會回傳明確的錯誤,因此工具不會在僅部分驗證過的排程上執行。

試想一個 50 分鐘的工作區間與一個 30 秒的休息。合併的循環為 50 × 60 + 30 = 3,030 秒。在經過 90 分鐘(5,400 秒)的已過時間後,循環中的位置 = 5,400 mod 3,030 = 2,370 秒。由於 2,370 小於循環中 3,000 秒的工作部分,網頁仍處於工作階段,剩餘時間為 3,000 − 2,370 = 630 秒,也就是距離下一次休息還有 10 分鐘 30 秒。這與計時器在每次更新時執行的計算相同,這就是為什麼顯示的剩餘時間與時鐘時間一致,而不會在回呼之間漂移。

瀏覽器限制是任何提醒都無法掩蓋的

準確度受到瀏覽器與作業系統所允許的限制。被推到背景的分頁可能會收到被節流的 setTimeoutsetInterval 回呼;睡眠中的筆電可能會完全暫停 JavaScript;低記憶體狀態可能會暫停渲染器;而關閉瀏覽器會立即停止所有計時器。如果在截止時間通過的那一刻頁面沒有執行中,任何工具都無法保證在那一個準確的瞬間響起聲音警報;工具只能保證,當執行恢復時,顯示的階段能反映時鐘時間。Break Reminder 不會掩蓋這個限制,而是將其揭露:網頁不會請求通知權限、也不會作為作業系統服務執行,其合約僅限於經過驗證的持續時間、以截止時間為基礎的階段轉換、網頁上的倒數、手動控制項,以及對瀏覽器排程限制的透明揭露。將可見的分頁視為排程的一部分,提醒就能與瀏覽器所允許的一樣準確。

如需更深入的瞭解,請參閱 Free Chess Clock: Two-Sided Timing with Fischer Increment

如需更深入的瞭解,請參閱 Double Click Test Accuracy: What the Interval Really Means