IndexedDB入门

分享于 

17分钟阅读

Web开发

  繁體 雙語

介绍

HTML5必须提供的新的JavaScript API之一是 IndexedDB。 过去,我写过关于的网页存储 API,它是存储在Web浏览器中的简单键/值字典,它保存了数据。 IndexedDB 是一个完整的索引数据库,它为Web应用程序增加了更多的离线功能。 本文将介绍 IndexedDB API,并解释一些关于它的基本概念。

背景- IndexedDB的功能?

IndexedDB API是在浏览器中存在的索引数据库的规范。 IndexedDB 是由保存简单值和分层对象的记录组成的。 每个记录都包含一个键路径和一个相应的值,它可以是 string 或者 date 等高级类型。 它可以包含索引以便更快地检索记录,并且可以存储大量的对象。

IndexedDB 有两种API模式- 同步和异步。 大多数情况下,你将使用异步 API。 创建同步API只用于与 Web worker的( 而且目前大多数浏览器都不支持它) 一起使用。

IndexedDB 是通过 window.indexedDB 对象公开的。 目前大多数浏览器都不完全支持这个 API。 支持API的主要浏览器使用它们的前缀公开 IndexedDB 对象。 在使用 IndexedDB 之前应该使用以下代码行,你应该使用 Modernizr 之类的库来检测浏览器是否支持该 API:

var indexedDB = window.indexedDB || window.webkitIndexedDB || 
 window.mozIndexedDB || window.msIndexedDB;

最后,在撰写文章时,IndexedDB从版本 4 (。Firefox 是最新更新的关于规范的浏览器) 支持,从版本 11和IE10支持 Chrome。

使用 IndexedDB API,可以将Web应用程序脱机并减少服务器数量,因为可以在本地数据库中存储常见数据。

打开数据库

首先要使用 IndexedDB,首先需要打开数据库以便使用。 由于 IndexedDB 工作异步调用 open 函数将返回 IDBRequest 对象,你将使用该对象来连接成功和错误事件处理程序。 以下是打开数据库的示例:

var db;var request = indexedDB.open("TestDatabase");
request.onerror = function(evt) {
 console.log("Database error code:" + evt.target.errorCode);
};
request.onsuccess = function(evt) {
 db = request.result;
};

示例中,使用 open 函数来打开名称为 TestDatabase的数据库。 调用后,两个回调函数连接到返回的IDBRequest,一个用于 onerror,一个用于 onsuccess。 成功回调中,可以从请求中获取数据库对象并存储它以便进一步使用。

open 函数接受另一个不在示例中传递的参数,该参数是数据库版本号。 版本号用于更改数据库的版本。 在数据库版本小于所提供的版本的情况下,将触发 upgradeneeded 事件,并能够更改数据库的结构。 改变数据库的版本是改变数据库结构的唯一途径。

创建一个仓库

IndexedDB 可以保存一个或者多个 objectStoresobjectStores 与关系数据库中的表相似,但它们与。 它们拥有键/值记录,并且可以有关键路径。关键生成器和索引。 你可以使用函数的IndexedDBcreateObjectStore 来创建 objectStore。 函数为 objectStore 和一个选项对象获取一个名称来配置关键路径和密钥生成器。

关键路径和密钥生成器用于创建存储值的主索引。 关键路径是一个 string,它定义如何从给定值中提取密钥。 它与具有键路径名称的属性的JavaScript对象一起使用。 如果具有确切名称的属性不存在,则需要提供一个密钥生成器,如 autoIncrement。 密钥生成器用于保存任何类型的值。 它会自动为你生成密钥,但也可以为存储的值传递自己的密钥,如果需要。

objectStores 还可以有索引,这些索引稍后将用于数据检索。 使用 objectStorecreateIndex 函数创建索引,该函数可以获取三个参数- 索引名称。属性的名称和选项对象。

下面是创建 onupdateneeded 事件处理程序的objectStore inside的示例:

var peopleData = [
 { name: "John Dow", email: "john@company.com" },
 { name: "Don Dow", email: "don@company.com" }
];function initDb() {
 var request = indexedDB.open("PeopleDB", 1); 
 request.onsuccess = function (evt) {
 db = request.result; 
 };
 request.onerror = function (evt) {
 console.log("IndexedDB error:" + evt.target.errorCode);
 };
 request.onupgradeneeded = function (evt) { 
 var objectStore = evt.currentTarget.result.createObjectStore("people", 
 { keyPath: "id", autoIncrement: true });
 objectStore.createIndex("name", "name", { unique: false });
 objectStore.createIndex("email", "email", { unique: true });
 for (i in peopleData) {
 objectStore.add(peopleData[i]);
 }
 };
}

这个例子展示了一些重要的事情:

  • onsuccess 回调之前调用 onupdateneeded,因此你可以使用 evt.currentTarget.result 获取打开的数据库。
  • 使用 id string 创建的键路径,该不存在于所提供的对象中。 密钥路径与 autoIncrement 选项一起使用,以创建递增的密钥生成器。
  • 你可以对索引使用唯一约束,以实施简单约束。 当唯一选项为 true 时,索引将强制对已经插入邮件执行约束。
  • 可以使用函数的objectStoreaddobjectStore 中添加记录。

创建事务

当你拥有 objectStore 时,你可能希望将它与 CRUD (create/read/update/delete) 操作一起使用。 在 IndexedDB 中使用CRUD的唯一方法是通过 IDBTransaction 对象。 当前的(。IndexedDB 对象) 前缀支持 IDBTransaction,因此应当使用以下代码行:

var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction;

可以在三种模式下创建 IDBTransaction 对象: 只读。读/写和快照。只要想更新 objectStores,只需在它的他情况下读取,即可以使用读/写模式。 它的原因是只读事务可以并发运行。 默认情况下,事务以只读模式运行。

事务是异步的,因为所有其他 IndexedDB API调用。 这意味着你可以为它们的errorabortcomplete 事件提供处理。 下面是打开 add 事务的示例:

var transaction = db.transaction("people", IDBTransaction.READ_WRITE);var objectStore = transaction.objectStore("people"); var request = objectStore.add({ name: name, email: email });
request.onsuccess = function (evt) {
 // do something when the add succeeded };

示例显示你首先为用户 objectStore 创建了一个 transaction 对象。 然后,从 transaction 对象检索 objectStore 并对它的执行操作。 这个操作称为异步操作,因此你可以连接 onsuccees 事件处理程序来处理请求的成功。 在本示例中,我没有连接任何事务事件处理程序,但你可以像下面的示例一样使用它们:

transaction.oncomplete = function(evt) { 
 // do something after the transaction completed };

获取数据

为了从 objectStore 中检索数据,你将使用 transaction 对象和函数的objectStoregetget 函数需要一个值,该值将被用于 objectStore的键路径。 下面是使用 get 函数的示例:

var transaction = db.transaction("people"); var objectStore = transaction.objectStore("people"); var request = objectStore.get(1); 
request.onsuccess = function(evt) { 
 alert("Name for id 1" + request.result.name); 
};

检索数据的另一种方法是使用 cursor。 你将在密钥路径未知时使用游标。 cursor 是针对 objectStore 打开的,是 transaction的一部分。 下面是使用 cursor的示例:

var transaction = db.transaction("people", IDBTransaction.READ_WRITE);var objectStore = transaction.objectStore("people");var request = objectStore.openCursor();
request.onsuccess = function(evt) { 
 var cursor = evt.target.result; 
 if (cursor) { 
 output.textContent += "id:" + cursor.key + " is" + cursor.value.name + ""; 
 cursor.continue(); 
 } 
 else { 
 console.log("No more entries!"); 
 } 
};

在这个例子中,openCursor 函数是针对 objectStore 调用的。 然后,将 onsuccess 函数连接到 cursor 请求,并用于写入名为输出的div,该数据被 cursor 检索到。 前面的示例是一个非常简单的cursor 示例。 cursor 可以与更复杂的查询一起使用,这些查询不会在本文中显示。

完整示例

下面是一些 IndexedDB 概念的完整示例:

<!DOCTYPEhtml><htmllang="en"><head><metacharset="utf-8"/><title>IndexedDB</title><scripttype="text/javascript">var indexedDB = window.indexedDB || window.webkitIndexedDB || 
 window.mozIndexedDB || window.msIndexedDB;
 var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction;
 var db;
 (function () { 
 var peopleData = [
 { name: "John Dow", email: "john@company.com" },
 { name: "Don Dow", email: "don@company.com" }
 ];
 function initDb() {
 var request = indexedDB.open("PeopleDB", 1); 
 request.onsuccess = function (evt) {
 db = request.result; 
 };
 request.onerror = function (evt) {
 console.log("IndexedDB error:" + evt.target.errorCode);
 };
 request.onupgradeneeded = function (evt) { 
 var objectStore = evt.currentTarget.result.createObjectStore(
 "people", { keyPath: "id", autoIncrement: true });
 objectStore.createIndex("name", "name", { unique: false });
 objectStore.createIndex("email", "email", { unique: true });
 for (i in peopleData) {
 objectStore.add(peopleData[i]);
 }
 };
 }
 function contentLoaded() {
 initDb(); 
 var btnAdd = document.getElementById("btnAdd");
 var btnDelete = document.getElementById("btnDelete");
 var btnPrint = document.getElementById("btnPrint"); 
 btnAdd.addEventListener("click", function () {
 var name = document.getElementById("txtName").value;
 var email = document.getElementById("txtEmail").value;
 var transaction = db.transaction("people", IDBTransaction.READ_WRITE);
 var objectStore = transaction.objectStore("people"); 
 var request = objectStore.add({ name: name, email: email });
 request.onsuccess = function (evt) {
 // do something after the add succeeded };
 }, false);
 btnDelete.addEventListener("click", function () {
 var id = document.getElementById("txtID").value;
 var transaction = db.transaction("people", IDBTransaction.READ_WRITE);
 var objectStore = transaction.objectStore("people");
 var request = objectStore.delete(id);
 request.onsuccess = function(evt) { 
 // It's gone!  };
 }, false);
 btnPrint.addEventListener("click", function () {
 var output = document.getElementById("printOutput");
 output.textContent = "";
 var transaction = db.transaction("people", IDBTransaction.READ_WRITE);
 var objectStore = transaction.objectStore("people");
 var request = objectStore.openCursor();
 request.onsuccess = function(evt) { 
 var cursor = evt.target.result; 
 if (cursor) { 
 output.textContent += "id:" + cursor.key + 
 " is" + cursor.value.name + ""; 
 cursor.continue(); 
 } 
 else { 
 console.log("No more entries!"); 
 } 
 }; 
 }, false); 
 }
 window.addEventListener("DOMContentLoaded", contentLoaded, false); 
 })(); 
 </script></head><body><divid="container"><labelfor="txtName"> Name:
 </label><inputtype="text"id="txtName"name="txtName"/><br/><labelfor="txtEmail"> Email:
 </label><inputtype="email"id="txtEmail"name="txtEmail"/><br/><inputtype="button"id="btnAdd"value="Add Record"/><br/><labelfor="txtID"> ID:
 </label><inputtype="text"id="txtID"name="txtID"/><br/><inputtype="button"id="btnDelete"value="Delete Record"/><br/><inputtype="button"id="btnPrint"value="Print objectStore"/><br/><outputid="printOutput"></output></div></body></html>
这里示例仅对 Firefox 10起作用,因为 Firefox 10是更新IndexedDB实现的唯一浏览器,使用最新的规范版本。

IndexedDB和Web存储 api

如在介绍中所写的,浏览器中有两种数据存储:IndexedDB 和Web存储。 我听到很多的问题之一是为什么要有两种不同的存储类型? 在很少数量的数据需要密钥/值对的简单场景中,Web存储比 IndexedDB 更适合于简化工作。 另一方面,在需要有效搜索值或者你要存储在客户端的大量对象的情况下,IndexedDB 是更好的。 这两个选项相互补充,可以在同一应用程序中一起使用。

摘要

IndexedDB 包括一个用于在浏览器中使用内置索引数据库的大型 API。 它可以用来存储客户端的数据,并使用Web存储来提供机会脱机并减少服务器循环。 有关 IndexedDB的更多信息,你可以在这里链接中转到它的规范。


STA  GET  index  Indexed  Indexeddb  
相关文章