日期:2014-05-16  浏览次数:20411 次

使用 IndexedDB

IndexedDB 是一种可以让你在用户的浏览器内持久化存储数据的方法。IndexedDB 为生成 Web Application 提供了丰富的查询能力,使我们的应用在在线和离线时都可以正常工作。

关于本文档

本篇教程将教会你如何使用 IndexedDB 的异步 API。如果你对 IndexedDB 还不熟悉,你应该首先阅读有关 IndexedDB 的基本概念。

有关 IndexedDB API 的参考手册,请参见 IndexedDB 这篇文章及其子页面,包括 IndexedDB 使用的对象类型,以及同步和异步 API 的方法。

基本模式

IndexedDB 鼓励使用的基本模式如下所示:

  1. 打开数据库并且开始一个事务。
  2. 创建一个 object store。
  3. 构建一个请求来执行一些数据库操作,像增加或提取数据等。
  4. 通过监听正确类型的 DOM 事件以等待操作完成。
  5. 在操作结果上进行一些操作(可以在 request 对象中找到)

生成和构建一个对象存储空间

由于 IndexedDB 本身的规范还在持续演进中,当前的 IndexedDB 的实现还是使用浏览器前缀。在规范更加稳定之前,浏览器厂商对于标准 IndexedDB API 可能都会有不同的实现。但是一旦大家对规范达成共识的话,厂商就会不带前缀标记地进行实现。实际上一些实现已经移除了浏览器前缀:IE 10,Firefox 16 和 Chrome 24。当使用前缀的时候,基于 Gecko 内核的浏览器使用 moz 前缀,基于 WebKit 内核的浏览器会使用 webkit 前缀。

使用体验版本的 IndexedDB

如果你希望在仍旧使用前缀的浏览器中测试你的代码, 可以使用下列代码:  

// In the following line, you should include the prefixes of implementations you want to test.
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
// DON'T use "var indexedDB = ..." if you're not in a function.
// Moreover, you may need references to some window.IDB* objects:
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange
// (Mozilla has never prefixed these objects, so we don't need window.mozIDB*)

要注意的是使用前缀的实现可能会有问题,或者是实现的并不完整,也可能遵循的还是旧版的规范。因此不建议在生产环境中使用。我们更倾向于明确的不支持某一浏览器,而不是声称支持但是实际运行中却出问题:

if (!window.indexedDB) {
    window.alert("Your browser doesn't support a stable version of IndexedDB. Such and such feature will not be available.")
}

打开数据库

我们像下面这样开始整个过程:

// 打开我们的数据库
var request = window.indexedDB.open("MyTestDatabase");

看到了吗? 打开数据库就像任何其他操作一样 — 你必须进行 "request"。

IndexedDB 对象只有一个单一方法,open(), 当这个方法被调用时,打开名为 "MyTestDatabase"的数据库。 所有 IndexedDB 数据库都按照同样的 origin 进行存储, 所以 mozilla.com 可能有一个名为 "binky" 的数据库,同时 mozilla.org 也可以有一个完全不同的名为 "binky" 的数据库。如果该数据库不存在,则会被创建;如果已经存在,则被打开。

open 请求不会立即打开数据库或者开始一个事务。 对 open() 函数的调用会返回一个我们可以作为事件来处理的包含 result(成功的话)或者错误值的 IDBOpenDBRequest 对象。在 IndexedDB 中的大部分异步方法做的都是同样的事情 - 返回一个包含 result 或错误的 IDBRequest 对象。open 函数的结果是一个 IDBDatabase对象的实例。

该 open 方法接受第二个参数,就是数据库的版本号。这样我们就可以更新数据库的 schema ,也就是说如果我们打开的数据库不是我们期望的最新版本的话,我们可以对 object store 进行创建或是删除。在这种情况下,我们实现一个 onupgradeneeded 处理函数,在一个允许操作 object stores 的 versionchange 事务中 - 我们在后面的 更新数据库的版本号中会提到更多有关这方面的内容。使用标明期望的版本号来打开数据库的示例如下所示: 

var request = indexedDB.open("MyTestDatabase", 3);

生成处理函数

几乎所有我们产生的请求我们在处理的时候首先要做的就是添加成功和失败处理函数:

request.onerror = function(event) {
  // Do something with request.errorCode!
};
request.onsuccess = function(event) {
  // Do something with request.result!
};

这两个函数的哪一个,onsuccess() 还是 onerror(),会被调用呢?如果一切顺利的话,一个 success 事件(即一个 type 属性被设置成 "success" 的 DOM 事件)会被触发,使用 request 作为它的 target。 一旦它被触发的话,相关 requestonsuccess() 函数就会被触发,使用 success 事件作为它的参数。 否则,如果不是所有事情都成功的话,一个 error 事件(即 type 属性被设置成 "err