解決 PWA 後台休眠:Web Worker 打造的心跳起搏器


解決 PWA 後台休眠:Web Worker 打造的心跳起搏器

在開發行動端 Web 應用程式時,開發者面臨的最大挑戰之一就是後台限制。現代手機操作系統 (iOS/Android) 為了極致省電,會對非活躍分頁進行無情的「降頻」甚至「凍結」。這對需要持續監控市場動態的 Hyperliquid Monitor 來說是個致命傷。

💀 問題:手機瀏覽器的「假死」 (The Problem)

當你鎖定螢幕,或切換到其他 App 時,Chrome 或 Safari 會認為當前網頁不再需要高性能運作。瀏覽器會將主線程的 setInterval 頻率降到極低(例如 1 分鐘才執行一次),甚至完全暫停執行。如果我們的監控系統需要每 10 秒檢查一次數據並發出警報,這種降頻會讓工具變得毫無意義。

✅ 解決方案:Web Worker 作為「計時起搏器」

為了繞過這個限制,我們引入了獨立的 timer.worker.js

技術原理

Web Worker 運行在與主 UI 線程完全獨立的線程中。雖然瀏覽器對後台 Worker 仍有限制,但其「被寬容度」通常比主線程高得多。

  1. 分離職責: 主 UI 線程負責渲染畫面與網絡請求,而 Worker 僅負責一件簡單的事:計時
  2. 訊息通訊:
    • 主線程啟動 Worker 並告知間隔時間(例如 10,000ms)。
    • Worker 內部啟動 setInterval,並在每次到點時發送一個簡單的 "tick" 訊息回主線程。
  3. 喚醒主流程: 主線程監聽到 Worker 的訊息後,被強行「喚醒」來執行重型的數據輪詢邏輯。

代碼實踐

Worker 線程 (timer.worker.js):

// Worker 保持「愚蠢」,只負責計時
self.onmessage = function(e) {
  if (e.data.action === 'start') {
    setInterval(() => self.postMessage('tick'), e.data.interval);
  }
};

主線程 (app.js):

if (window.Worker) {
  const pollWorker = new Worker('timer.worker.js');
  pollWorker.onmessage = (e) => {
    if (e.data === 'tick') pollLatest(); // 被喚醒,執行數據抓取
  };
  pollWorker.postMessage({ action: 'start', interval: 10000 });
}

⚖️ 權衡與代價

雖然 Web Worker 方案大幅提升了鎖屏後的警報可靠性(實測在 Android 下鎖屏 30 分鐘仍能穩定運行),但它並非萬能藥:

  • 非原生後台: 這仍受限於瀏覽器進程的生命週期。如果系統記憶體吃緊,整個瀏覽器仍可能被殺死。
  • 記憶體佔用: 多開一個線程會增加些微的資源開銷。

結論

在純 Web 技術的限制下,利用 Web Worker 作為「心跳起搏器」是實現高頻後台監控的最優解。它平衡了電力消耗與任務實時性,為 PWA 應用程式開啟了更多可能性。