IndexedDB 關鍵特性和基本術語
本文介紹了 IndexedDB 的主要特性,並引入了一些理解 IndexedDB API 所必需的基本術語。
您還會發現以下文章很有用
- 有關如何使用該 API 的詳細教程,請參閱 使用 IndexedDB。
- 有關 IndexedDB API 的參考文件,請參閱主 IndexedDB API 文章及其子頁面,其中記錄了 IndexedDB 使用的物件型別。
- 有關瀏覽器如何在後臺處理資料儲存的更多資訊,請閱讀 瀏覽器儲存配額和逐出標準。
主要特性
IndexedDB 是一種在使用者瀏覽器中持久儲存資料的方式。因為它允許您建立具有豐富查詢功能的 Web 應用程式,而無論網路是否可用,這些應用程式既可以線上工作也可以離線工作。IndexedDB 對於儲存大量資料(例如,借閱圖書館的 DVD 目錄)的應用程式以及不需要持久網際網路連線即可工作的應用程式(例如,郵件客戶端、待辦事項列表和記事本)非常有用。
IndexedDB 允許您儲存和檢索使用“鍵”索引的物件。您對資料庫所做的所有更改都發生在事務中。像大多數 Web 儲存解決方案一樣,IndexedDB 遵循同源策略。因此,您可以在一個域內訪問儲存的資料,但不能跨不同域訪問資料。
如果您對使用其他型別資料庫有先入之見,那麼在使用 IndexedDB 時可能會感到困惑。因此,以下 IndexedDB 的關鍵特性需要牢記:
-
IndexedDB 資料庫儲存鍵值對。值可以是複雜的結構化物件,鍵可以是這些物件的屬性。您可以建立使用物件任何屬性的索引,以便快速搜尋和排序列舉。鍵可以是二進位制物件。
-
IndexedDB 基於事務資料庫模型構建。您在 IndexedDB 中所做的一切都始終在事務的上下文中發生。IndexedDB API 提供了許多表示索引、表、遊標等的物件,但這些物件都繫結到特定的事務。因此,您不能在事務之外執行命令或開啟遊標。事務具有明確定義的生命週期,因此在事務完成後嘗試使用它會丟擲異常。此外,如果在事務處於活動狀態時沒有發出新的請求,事務會自動提交。
當您考慮如果使用者同時在兩個不同的選項卡中開啟您的 Web 應用程式的兩個例項時可能發生的情況,這種事務模型非常有用。如果沒有事務操作,這兩個例項可能會相互干擾修改。如果您不熟悉資料庫中的事務,請閱讀維基百科關於事務的文章。另請參閱定義部分中的事務。
-
IndexedDB API 大部分是非同步的。該 API 不透過返回值來提供資料;相反,您必須傳遞一個回撥函式。您不能透過同步方式將值“儲存”到資料庫中,也不能從資料庫中“檢索”值。相反,您“請求”資料庫操作發生。當操作完成時,您會收到 DOM 事件通知,您收到的事件型別會告訴您操作成功還是失敗。
-
IndexedDB 使用大量請求。請求是接收前面提到的成功或失敗 DOM 事件的物件。它們具有
onsuccess和onerror屬性,您可以在它們上呼叫addEventListener()和removeEventListener()。它們還具有readyState、result和errorCode屬性,用於告訴您請求的狀態。result屬性尤其神奇,因為它可以是許多不同的東西,具體取決於請求是如何生成的(例如,一個IDBCursor例項,或者您剛剛插入到資料庫中的值的鍵)。 -
IndexedDB 使用 DOM 事件通知您何時結果可用。DOM 事件總是有一個
type屬性(在 IndexedDB 中,它最常設定為"success"或"error")。DOM 事件也有一個target屬性,指示事件的目標。在大多數情況下,事件的target是由於執行某些資料庫操作而生成的IDBRequest物件。成功事件不會冒泡,也不能取消。另一方面,錯誤事件會冒泡,並且可以取消。這非常重要,因為錯誤事件會中止它們正在執行的任何事務,除非它們被取消。 -
IndexedDB 是面向物件的。IndexedDB 不是一個關係型資料庫,其中表表示行和列的集合。這種重要而根本的區別會影響您設計和構建應用程式的方式。
在傳統的關係資料儲存中,您會有一個表,其中儲存著行資料集合和命名資料型別的列。而 IndexedDB 則要求您為一種資料型別建立一個物件儲存,並將 JavaScript 物件持久化到該儲存中。每個物件儲存可以擁有一組索引,這些索引使得查詢和迭代效率更高。如果您不熟悉面向物件資料庫管理系統,請閱讀維基百科上關於物件資料庫的文章。
-
IndexedDB 不使用結構化查詢語言 (SQL)。它使用對索引的查詢來生成遊標,您可以使用該遊標遍歷結果集。如果您不熟悉 NoSQL 系統,請閱讀維基百科上關於 NoSQL 的文章。
-
IndexedDB 遵循同源策略。源是執行指令碼的文件 URL 的域、應用層協議和埠。每個源都有其自己關聯的資料庫集。每個資料庫都有一個名稱,用於在源中標識它。
IndexedDB 施加的安全邊界阻止應用程式訪問不同源的資料。例如,
http://www.example.com/app/中的應用程式或頁面可以從http://www.example.com/dir/檢索資料,因為它們具有相同的源,但它不能從http://www.example.com:8080/dir/(不同埠)或https://www.example.com/dir/(不同協議)檢索資料,因為它們具有不同的源。注意:第三方視窗內容(例如,
內容)可以訪問其嵌入的源的 IndexedDB 儲存,除非瀏覽器設定為永不接受第三方 cookie(參見Firefox bug 1147821)。
侷限性
IndexedDB 旨在覆蓋大多數需要客戶端儲存的情況。但是,它並非為以下幾種情況而設計:
- 國際化排序。並非所有語言都以相同的方式對字串進行排序,因此不支援國際化排序。雖然資料庫無法以特定的國際化順序儲存資料,但您可以自己對從資料庫中讀取的資料進行排序。
- 同步。該 API 未設計用於與伺服器端資料庫同步。您必須編寫程式碼來同步客戶端 IndexedDB 資料庫與伺服器端資料庫。
- 全文搜尋。該 API 沒有 SQL 中
LIKE運算子的等效項。
此外,請注意,瀏覽器可能會在以下情況下清除資料庫:
- 使用者請求清除。許多瀏覽器都有設定,允許使用者清除給定網站儲存的所有資料,包括 cookie、書籤、儲存的密碼和 IndexedDB 資料。
- 瀏覽器處於私密瀏覽模式。一些瀏覽器有“私密瀏覽”(Firefox)或“隱身”(Chrome)模式。在會話結束時,瀏覽器會清除資料庫。
- 磁碟或配額限制已達到。
- 資料已損壞。
- 對功能進行了不相容的更改。
具體情況和瀏覽器功能會隨著時間而變化,但瀏覽器供應商的普遍理念是儘可能地努力保留資料。
核心術語
本節定義並解釋了理解 IndexedDB API 的核心術語。
資料庫
資料庫
資訊的儲存庫,通常包含一個或多個物件儲存。每個資料庫必須具備以下特點:
- 名稱。用於在特定源中標識資料庫,並在其生命週期內保持不變。名稱可以是任何字串值(包括空字串)。
- 當前版本。資料庫首次建立時,如果未另行指定,其版本為整數 1。每個資料庫在任何給定時間只能有一個版本。
資料庫連線
透過開啟資料庫建立的操作。一個給定的資料庫可以同時有多個連線。
永續性
在 Firefox 中,IndexedDB 曾經是持久的,這意味著在讀寫事務中,complete 事件僅在所有資料都保證已重新整理到磁碟時才觸發。
自 Firefox 40 起,IndexedDB 事務放寬了永續性保證以提高效能(參見Firefox bug 1112702),這與其他支援 IndexedDB 的瀏覽器行為相同。在這種情況下,complete 事件在作業系統被告知寫入資料之後但在資料實際重新整理到磁碟之前可能觸發。因此,該事件可能會比以前更快地傳遞,但是,如果作業系統崩潰或在資料重新整理到磁碟之前系統斷電,則整個事務可能會丟失。由於此類災難性事件很少見,大多數使用者無需進一步關注。
注意:在 Firefox 中,如果您出於某種原因希望確保永續性(例如,您正在儲存無法稍後重新計算的關鍵資料),您可以透過使用實驗性(非標準)readwriteflush 模式建立事務,強制事務在傳遞 complete 事件之前重新整理到磁碟(參見IDBDatabase.transaction)。這目前是實驗性的,並且只有在 about:config 中將 dom.indexedDB.experimental 首選項設定為 true 時才能使用。
index
索引是一個專門的物件儲存,用於在另一個名為引用物件儲存的物件儲存中查詢記錄。索引是持久的鍵值儲存,其記錄的值部分是引用物件儲存中記錄的鍵部分。索引中的記錄在引用物件儲存中的記錄被插入、更新或刪除時會自動填充。索引中的每條記錄只能指向其引用物件儲存中的一條記錄,但多個索引可以引用同一個物件儲存。當物件儲存發生變化時,所有引用該物件儲存的索引都會自動更新。
或者,您也可以使用鍵在物件儲存中查詢記錄。
要了解更多關於使用索引的資訊,請參閱使用 IndexedDB。有關索引的參考文件,請參閱IDBKeyRange。
物件儲存
資料在資料庫中儲存的機制。物件儲存持久地儲存記錄,記錄是鍵值對。物件儲存中的記錄根據鍵按升序排序。
每個物件儲存必須有一個在其資料庫中唯一的名稱。物件儲存可以選擇具有一個鍵生成器和一個鍵路徑。如果物件儲存具有鍵路徑,則它使用內聯鍵;否則,它使用非內聯鍵。
有關物件儲存的參考文件,請參閱IDBObjectStore。
請求
對資料庫進行讀寫操作。每個請求代表一個讀或寫操作。
事務
對特定資料庫進行資料訪問和資料修改操作的原子集合。它是您與資料庫中的資料互動的方式。事實上,資料庫中任何資料的讀取或更改都必須在事務中進行。
一個數據庫連線可以同時關聯多個活動事務,只要寫入事務沒有重疊的範圍。事務的範圍在建立時定義,它決定了事務可以與哪些物件儲存互動,並在事務的生命週期內保持不變。因此,例如,如果一個數據庫連線已經有一個範圍只覆蓋 flyingMonkey 物件儲存的寫入事務,您可以啟動第二個事務,其範圍為 unicornCentaur 和 unicornPegasus 物件儲存。至於讀取事務,您可以有多個——甚至可以有重疊的。
事務預期是短命的,因此瀏覽器可能會終止耗時過長的事務,以釋放長時間執行事務鎖定的儲存資源。您可以中止事務,這將回滾在事務中對資料庫所做的更改。您甚至不需要等待事務開始或啟用即可中止它。
事務有三種模式:readwrite、readonly 和 versionchange。建立和刪除物件儲存和索引的唯一方法是使用versionchange事務。要了解更多關於事務型別的資訊,請參閱IndexedDB的參考文章。
由於一切都發生在事務中,因此它是 IndexedDB 中一個非常重要的概念。要了解有關事務的更多資訊,尤其是它們與版本控制的關係,請參閱IDBTransaction,其中也包含參考文件。
版本
當資料庫首次建立時,其版本為整數 1。每個資料庫同時只有一個版本;一個數據庫不能同時存在於多個版本中。更改版本的唯一方法是使用比當前版本更高的版本開啟它。
鍵和值
內聯鍵
作為儲存值的一部分儲存的鍵。它透過鍵路徑找到。內聯鍵可以使用生成器生成。鍵生成後,可以使用鍵路徑將其儲存在值中,也可以將其用作鍵。
key
用於在物件儲存中組織和檢索儲存值的資料值。物件儲存可以從三個來源之一派生鍵:鍵生成器、鍵路徑或顯式指定的值。鍵的資料型別必須是數字大於前一個數字的資料型別。物件儲存中的每個記錄都必須有一個在該儲存中唯一的鍵,因此在給定的物件儲存中不能有多個具有相同鍵的記錄。
鍵可以是以下型別之一:字串、日期、浮點數、二進位制大物件和陣列。對於陣列,鍵的範圍可以從空值到無窮大。您可以在陣列中包含陣列。
或者,您也可以使用索引在物件儲存中查詢記錄。
鍵生成器
一種按有序序列生成新鍵的機制。如果物件儲存沒有鍵生成器,則應用程式必須為要儲存的記錄提供鍵。生成器在儲存之間不共享。這更像是一個瀏覽器實現細節,因為在 Web 開發中,您實際上不會建立或訪問鍵生成器。
鍵路徑
定義瀏覽器應該從物件儲存或索引中提取鍵的位置。有效的鍵路徑可以包含以下之一:空字串、JavaScript 識別符號、由句點分隔的多個 JavaScript 識別符號,或包含其中任何一個的陣列。它不能包含空格。
非內聯鍵
與被儲存的值分開儲存的鍵。
value
每條記錄都有一個值,其中可以包含任何可以用 JavaScript 表達的內容,包括布林值、數字、字串、日期、物件、陣列、正則表示式、undefined 和 null。
當儲存一個物件或陣列時,該物件或陣列中的屬性和值也可以是任何有效值。
二進位制大物件 (Blob) 和檔案可以儲存,請參閱規範。
範圍和作用域
cursor
一種使用鍵範圍迭代多個記錄的機制。遊標有一個源,指示它正在迭代哪個索引或物件儲存。它在範圍內有一個位置,並按照記錄鍵的順序向遞增或遞減方向移動。有關遊標的參考文件,請參閱IDBCursor。
鍵範圍
用於鍵的某種資料型別上的連續區間。可以使用鍵或鍵範圍從物件儲存和索引中檢索記錄。您可以使用下限和上限來限制或過濾範圍。例如,您可以迭代鍵在 x 和 y 之間的所有值。
有關鍵範圍的參考文件,請參閱IDBKeyRange。
scope
事務應用於的物件儲存和索引的集合。只讀事務的範圍可以重疊並同時執行。另一方面,寫入事務的範圍不能重疊。您仍然可以同時啟動具有相同範圍的多個事務,但它們只是排隊並一個接一個地執行。
後續步驟
瞭解了 IndexedDB 的主要特性和核心術語之後,我們可以開始更具體的內容。有關如何使用該 API 的教程,請參閱使用 IndexedDB。