題干與適用場景
這是前端系統設計與狀態管理的交叉題。重點是把本機資料、同步佇列、伺服器版本與使用者看得到的狀態連起來,不只是加一層快取。
面試官考察什麼
- 能否分開本機草稿、待同步操作與伺服器確認狀態。
- 能否選擇合適的衝突策略,說明哪些欄位不能自動合併。
- 能否處理重試、重複提交、瀏覽器關閉與多分頁。
- 能否讓離線、同步中、衝突和失敗狀態可理解、可恢復。
回答前需要釐清的問題
先確認欄位是否獨立、是否有稽核或金額等高風險欄位;離線編輯是否必須支援附件;伺服器是否提供版本號或操作日誌;可否採最後寫入獲勝,還是需要欄位級合併或人工確認;以及瀏覽器支援範圍與本機資料保留期限。
30 秒回答架構
我會以 IndexedDB 作為本機持久層,把每次編輯記成帶有 clientMutationId 與基線版本的操作。介面立即顯示本機狀態並標示待同步;Service Worker 或應用啟動時批次送出佇列。伺服器用版本檢查和冪等鍵回覆成功、衝突或驗證失敗。可安全合併的欄位自動處理,高風險欄位顯示差異讓使用者選擇,所有狀態都能重試或撤銷。
分步驟深入解答
1. 先定義狀態模型
每份草稿至少有 serverVersion、localVersion、syncState 與 lastError。每個待送操作保存 clientMutationId、欄位變更、建立時間與基線版本。讀取優先來自本機儲存,網路回應只有在確認版本後才合併,避免回應順序覆蓋較新的編輯。
2. 用 IndexedDB 保存可恢復事實
IndexedDB 適合保存較大的結構化離線資料,但要處理 schema 升級、空間不足與瀏覽器清理。將草稿、操作佇列和衝突紀錄分開,以交易確保草稿與佇列同時落盤。敏感表單只保留必要欄位,登出或到期時清除。
3. 設計同步觸發與冪等協定
線上時可立即嘗試送出,離線時進入佇列;支援 Background Sync 時可註冊唯一 tag 交給 Service Worker,但不能把它當成所有瀏覽器都可靠提供的保證。每次請求帶 clientMutationId 與基線版本,伺服器重複收到同一 id 時回傳同一結果,不重複套用。
4. 讓衝突策略符合欄位風險
標題、標籤等獨立欄位可按欄位版本合併;金額、權限與合規聲明不能簡單採最後寫入獲勝。伺服器回傳衝突時,介面並列本機值、伺服器值與修改時間,使用者選擇後產生新操作。自動合併必須記錄來源,不能靜默覆蓋。
5. 處理失敗、重試與多個上下文
網路失敗使用指數退避並保留佇列順序;驗證失敗進入可編輯的錯誤狀態,不要無限重試。多分頁用 BroadcastChannel 或版本檢查互相通知,避免兩個頁面同時送出舊操作。瀏覽器關閉後,已落盤佇列在下次啟動繼續處理。
高品質示範回答
我會先按欄位風險與離線邊界定義需求。客戶端以 IndexedDB 保存草稿與操作佇列,每次操作帶 clientMutationId 和基線 serverVersion;UI 先顯示本機結果並標示待同步。線上或恢復連線後,應用程式或 Service Worker 傳送佇列,伺服器用版本檢查與冪等鍵回覆成功、衝突或驗證錯誤。獨立欄位可以自動合併,高風險欄位則展示本機與伺服器差異,讓使用者確認後再提交。網路失敗可退避重試,業務失敗進入可修改狀態;多分頁透過版本通知避免舊資料覆蓋。介面提供離線、同步中、衝突、失敗與已儲存的明確狀態。
常見錯誤
- 只快取最後一份表單,沒有操作佇列和版本基線。
- 用時間戳或最後寫入獲勝處理所有欄位。
- 把 Background Sync 當成所有瀏覽器都會觸發的保證。
- 重試沒有冪等鍵,造成重複建立或扣款。
- 衝突只在主控台報錯,使用者不知道如何恢復。
- 忽略 schema 升級、儲存配額、多分頁與瀏覽器關閉。
追問及應對
使用者在兩個分頁同時編輯怎麼辦?
每個分頁訂閱版本變化,發現本機基線過期就提示合併;送出前再次做版本檢查。共同的操作 id 仍由伺服器去重。
離線資料會不會外洩?
依業務需要最小化本機欄位,敏感內容加密並縮短保留時間;登出、共用裝置或策略變更時清除本機資料。
瀏覽器不支援 Background Sync 呢?
以應用啟動、頁面重新取得焦點、網路狀態變化和短輪詢作為降級觸發,並在介面說明仍有待同步紀錄。核心正確性不能依賴這個 API。
什麼時候允許自動合併?
只有欄位語意獨立、版本基線明確且業務接受暫時差異時才自動合併。金額、權限、庫存或稽核欄位應要求明確確認。