HTML5 的一个重要特性是本地数据持久性,它使用户能够在线和离线访问 Web 应用程序。此外,本地数据持久性使">移动应用程序更灵敏,使用的带宽更少,而且能够在低带宽场景中更高效地工作。HTML5 提供了一些本地数据持久性选项。第一个选项是 localstorage,它支持您使用一个简单的键值对来存储数据。IndexedDB(一个更加强大的选项)支持您本地存储大量对象,并使用健壮的数据访问机制检索数据。
IndexedDB API 取代了 Web Storage API,后者在 HTML5 规范中已不推荐使用。(但一些领先的浏览器仍然支持 Web Storage,其中包括苹果公司的 Safari 和 Opera Web 浏览器)与 Web Storage 相比,IndexedDB 具有多个优势,其中包括索引、事务处理和健壮的查询功能。本文将通过一系列的示例来展示如何管理 IndexedDB 数据库。
重要概念
一个网站可能有一个或多个 IndexedDB 数据库,每个数据库必须具有惟一的名称。
一个数据库可包含一个或多个对象存储。一个对象存储(由一个名称惟一标识)是一个记录集合。每个记录有一个键 和一个值。该值是一个对象,可拥有一个或多个属性。键可能基于某个键生成器,从一个键路径衍生出来,或者是显式设置。一个键生成器自动生成惟一的连续正整数。键路径定义了键值的路径。它可以是单个 JavaScript 标识符或多个由句点分隔的标识符。
规范中包含一个异步 API 和一个同步 API。同步 API 用于 Web 浏览器中。异步 API 使用请求和回调。
在以下示例中,输出附加到一个具有 ID result 的 div 标记上。要更新 result 元素,可在每个数据操作期间清除并设置 innerHTML 属性。每个示例 JavaScript 函数由 HTML 按钮的一个 onclick 事件调用。
处理错误或异常和调试
所有异步请求都有一个 onsuccess 回调和一个 onerror 回调,前者在数据库操作成功时调用,后者在一个操作未成功时调用。清单 1 是一个 onerror 回调的示例。
清单 1. 异步错误处理函数
request.onerror =
function(e) { // handle error ... console.log("Database error: " + e.target.errorCode);};
在使用 IndexedDB API 时,使用 JavaScript try/catch 块是一个不错的想法。此功能对处理可能在数据库操作之前发生的错误和异常很有用,比如在数据库未打开时尝试读取或操作数据,或者在另一个读/写事务已打开时尝试写入数据。
IndexedDB 很难调试和排除故障,因为在许多情况下,错误消息是泛泛的,缺乏信息价值。在开发应用程序时,可以使用 console.log 和 JavaScript 调试工具,比如用于 Mozilla Firefox 的 Firebug,或者 Chrome 内置的 Developer Tools。对于任何 JavaScript 密集型应用程序,这些工具的价值是无可估量的,它们尤其适用于使用 IndexedDB API 的 HTML5 应用程序。
使用数据库
一个数据库一次只能有一个版本。在首次创建数据库时,它的初始版本编号为 0。创建数据库之后,数据库(和它的对象存储)只能通过一种称为 versionchange 的特殊类型的事务来更改。要在创建数据库后更改它,必须打开具有更高版本的数据库。此操作会触发 upgradeneeded 事件。修改数据库或对象存储的代码必须位于 upgradeneeded 事件处理函数中。
清单 2 中的代码段展示了如何创建数据库:调用 open 方法并传递数据库名称。如果不存在具有指定名称的数据库,则会创建该数据库。
清单 2. 创建一个新的数据库
function createDatabase() { var openRequest = localDatabase.indexedDB.open(dbName); openRequest.onerror = function(e) { console.log("Database error: " + e.target.errorCode); }; openRequest.onsuccess = function(event) { console.log("Database created"); localDatabase.db = openRequest.result; }; openRequest.onupgradeneeded = function (evt) { ... };}
要删除现有数据库,可以调用 deleteDatabase 方法,并传递要删除的数据库名称,如 清单 3 中所示。
清单 3. 删除现有数据库
function deleteDatabase() { var deleteDbRequest = localDatabase.indexedDB.deleteDatabase(dbName); deleteDbRequest.onsuccess = function (event) { // database deleted successfully }; deleteDbRequest.onerror = function (e) { console.log("Database error: " + e.target.errorCode); };}
清单 4 中的代码段展示了如何打开与现有数据库的连接。
清单 4. 打开数据库的最新版本
function openDatabase() { var openRequest = localDatabase.indexedDB.open("dbName"); openRequest.onerror = function(e) { console.log("Database error: " + e.target.errorCode); }; openRequest.onsuccess = function(event) { localDatabase.db = openRequest.result; };}
创建、删除和打开数据库就是这么简单。现在是时候使用对象存储了。