具代表性的面試主題

如何用 Web Locks API 協調多個分頁的共享任務?

前端困難
OfferCC 編輯團隊發佈 更新

題幹

一個 Web 應用程式可能同時開啟多個分頁,但只能有一個分頁刷新共享快取並執行同步任務。請用 Web Locks API 設計協調方案,並說明鎖的作用域、排隊、ifAvailable、AbortSignal、分頁崩潰和不支援時的降級。

1. 題目

多個同源分頁會同時嘗試刷新 IndexedDB 中的快取並向伺服器同步。請設計一個協調器,保證同一時間最多一個上下文執行同步,其他分頁可以等待、跳過或在鎖釋放後重新檢查狀態。方案還要涵蓋分頁關閉、網路失敗和瀏覽器不支援 Web Locks 的情況。

2. 約束與釐清

  • 鎖名在同源上下文之間共享,頁面和 Worker 都可能參與競爭。
  • 鎖只保護協調範圍內的非同步回呼;它不是資料庫交易,也不能取代伺服器並發控制。
  • 同步任務可能耗時,需要可取消、可重試,並在完成後廣播結果或版本號。
  • 需要區分等待鎖、立即探測鎖和放棄請求三種呼叫意圖。

3. 核心思路

呼叫 navigator.locks.request(name, options, callback) 請求命名鎖。鎖會在回呼 Promise 完成後釋放;因此回呼必須包含完整的讀取、同步和狀態寫入流程。預設請求會排隊,ifAvailable: true 可以在鎖忙碌時立即收到 null,signal 可取消仍在等待的請求。

鎖管理器會在持有上下文終止時釋放鎖,但持鎖頁面崩潰不應成為業務正確性的唯一依據:同步記錄應帶版本、租期或冪等鍵,伺服器仍需校驗。其他分頁可透過 BroadcastChannel 或重新讀取 IndexedDB 發現新版本。

4. 參考實作

javascript
const LOCK = "shared-cache-sync";

async function runSync(signal) {
  return navigator.locks.request(LOCK, { signal }, async (lock) => {
    if (!lock) return { status: "busy" };
    const current = await readSyncVersion();
    if (await isFresh(current)) return { status: "fresh" };
    const result = await fetchAndWriteCache({ signal, baseVersion: current });
    await publishVersion(result.version);
    return { status: "updated", version: result.version };
  });
}

async function trySyncWithoutWaiting() {
  return navigator.locks.request(
    LOCK,
    { ifAvailable: true },
    (lock) => lock ? runOneSync() : { status: "busy" },
  );
}

5. 正確性與故障處理

鎖保證的是同源上下文對同一名稱的互斥排隊,不保證網路請求或資料庫寫入自動回滾。回呼應先重新讀取版本,再執行條件更新;如果同步期間網路失敗,拋出錯誤讓鎖釋放,並由下一次請求重試。不要在鎖回呼之外保存「我擁有鎖」的布林值。

等待請求被 AbortSignal 取消時,呼叫端要區分取消與業務失敗。對於長時間等待,可以顯示「其他分頁正在同步」或直接跳過;鎖釋放後再讀取版本,避免重複刷新。同步結果透過 BroadcastChannel 通知只是最佳化,權威狀態仍應來自 IndexedDB 或伺服器。

6. 追問與陷阱

  • Web Locks 只在同源上下文間協調,不能鎖住另一個網站、伺服器程序或資料庫資料列。
  • ifAvailable 不會排隊;拿不到鎖時回呼收到 null,不能把它當成例外。
  • steal: true 會破壞既有排隊語意,應只用於明確可丟棄的工作,並搭配版本檢查。
  • 不支援 API 時可用 BroadcastChannel 加 IndexedDB 記錄做盡力協調,但不能宣稱有同等互斥保證;伺服器必須繼續防重複。

7. 延伸閱讀

可以比較 Web Locks、IndexedDB 交易、Service Worker 訊息和 BroadcastChannel:鎖解決跨上下文互斥,交易解決單庫原子性,訊息通道負責通知。跨裝置或跨使用者的互斥應移到伺服器租約、冪等 API 或資料庫約束。

8. 面試評分點

能說明鎖的作用域

應指出命名鎖只協調同源視窗與 Worker,回呼 Promise 完成才釋放,不能取代伺服器或資料庫並發控制。

能區分三種請求模式

應分別解釋預設排隊、ifAvailable 立即探測和 AbortSignal 放棄等待的行為。

能處理崩潰與重複

應使用版本、冪等鍵和條件更新,說明分頁崩潰釋放鎖不等於業務寫入自動回滾。

能給出誠實降級

應提供 BroadcastChannel/IndexedDB 的盡力方案,並明確互斥保證降低、伺服器仍需兜底。

公開來源

同類題目

資源

產品比較

每份比較均依官方資料整理,並標示複核日期。

查看完整比較