瞭解在 IndexedDB 和熱門狀態管理程式庫之間同步處理應用程式狀態的最佳做法。
使用者首次載入網站或應用程式時,通常需要進行大量工作,才能建構用於轉譯 UI 的初始應用程式狀態。舉例來說,有時應用程式需要先在用戶端驗證使用者,然後提出多項 API 要求,才能取得要在頁面上顯示的所有資料。
將應用程式狀態儲存在 IndexedDB 中,可有效縮短重複造訪時的載入時間。接著,應用程式可以在背景與任何 API 服務同步,並採用過時重新驗證策略,以延遲方式更新 UI。
不過,使用 IndexedDB 時,有許多重要事項需要考量,但對於剛接觸 API 的開發人員來說,可能不會立即察覺。本文將回答常見問題,並探討在 IndexedDB 中保留應用程式狀態時,需要注意的一些重要事項。
確保應用程式提供可預期的體驗
IndexedDB 的許多複雜問題,都源自於有太多因素是您 (開發人員) 無法控制的。本節將探討使用 IndexedDB 時必須留意的許多問題。
寫入儲存空間可能失敗
寫入 IndexedDB 時發生錯誤的原因有很多,在某些情況下,這些原因並非開發人員所能控制。舉例來說,部分瀏覽器不允許在私密瀏覽模式下寫入 IndexedDB。此外,如果使用者裝置的磁碟空間即將用盡,瀏覽器也會限制您儲存任何內容。
因此,請務必在 IndexedDB 程式碼中,一律實作適當的錯誤處理機制。這也表示,除了儲存應用程式狀態外,通常最好也將狀態保留在記憶體中,這樣一來,在私密瀏覽模式下執行或儲存空間不足時,UI 就不會中斷 (即使某些需要儲存空間的其他應用程式功能無法運作)。
使用者可能已修改或刪除儲存的資料
伺服器端資料庫可限制未經授權的存取,但用戶端資料庫可由瀏覽器擴充功能和開發人員工具存取,且使用者可清除資料。
雖然使用者不常修改儲存在本機的資料,但清除資料的情況相當常見。請務必確保應用程式能處理這兩種情況,且不會發生錯誤。
儲存的資料可能已過時
與上一節類似,即使使用者未自行修改資料,儲存空間中的資料也可能是由舊版程式碼寫入,而該版本可能含有錯誤。
IndexedDB 內建支援結構定義版本,並使用 IDBOpenDBRequest.onupgradeneeded() 方法進行升級;不過,您仍需編寫升級程式碼,以便處理來自舊版本 (包括有錯誤的版本) 的使用者。
單元測試在這方面非常實用,因為手動測試所有可能的升級路徑和案例通常不可行。
確保應用程式效能
IndexedDB 的其中一項重要功能是非同步 API,但請不要誤以為使用時不必擔心效能問題。在許多情況下,不當使用仍可能導致主執行緒遭到封鎖,進而造成無回應。
一般來說,IndexedDB 的讀取和寫入作業不應超過存取資料所需的大小。
雖然 IndexedDB 可以將大型巢狀物件儲存為單一記錄 (從開發人員的角度來看,這樣做確實相當方便),但應避免這種做法。這是因為 IndexedDB 儲存物件時,必須先建立該物件的結構化複製,而結構化複製程序會在主執行緒上進行。物件越大,封鎖時間就越長。
在規劃如何將應用程式狀態保存至 IndexedDB 時,這會帶來一些挑戰,因為大多數熱門的狀態管理程式庫 (例如 Redux) 都是將整個狀態樹狀結構做為單一 JavaScript 物件來管理。
雖然以這種方式管理狀態有許多好處,而且將整個狀態樹狀結構儲存為 IndexedDB 中的單一記錄可能很吸引人且方便,但在每次變更後執行這項操作 (即使經過節流/去抖動),會導致主執行緒不必要地遭到封鎖,增加寫入錯誤的可能性,在某些情況下甚至會導致瀏覽器分頁當機或沒有回應。
請勿將整個狀態樹狀結構儲存在單一記錄中,而是應將其拆分為個別記錄,並僅更新實際變更的記錄。
與大多數最佳做法一樣,這並非絕對規則。如果無法拆分狀態物件並只寫入最小變更集,建議您將資料拆分為子樹狀結構,並只寫入這些子樹狀結構,而不是一律寫入整個狀態樹狀結構。小幅改善總比完全不改善好。
最後,請務必評估編寫程式碼對效能的影響。雖然 IndexedDB 的小型寫入作業效能確實優於大型寫入作業,但只有在應用程式對 IndexedDB 的寫入作業實際導致長時間任務,進而阻斷主執行緒並降低使用者體驗時,這點才重要。請務必評估成效,瞭解要最佳化的項目。
結論
開發人員可以使用 IndexedDB 等用戶端儲存機制,改善應用程式的使用者體驗,不僅能跨工作階段保留狀態,還能縮短重複造訪時載入初始狀態所需的時間。
正確使用 IndexedDB 可大幅改善使用者體驗,但如果使用不當或無法處理錯誤情況,可能會導致應用程式故障,讓使用者不滿。
由於用戶端儲存空間涉及許多您無法控制的因素,因此請務必妥善測試程式碼,並正確處理錯誤,即使是最初看似不太可能發生的錯誤也一樣。