在 浏览器数据库 IndexedDB 简明教程 ( 三 ) - 能用否 ? 中我们学习了如何判断浏览器是否支持 IndexedDB,同时也阐述了针对不支持的浏览器的一种解决方案。我并没有推荐使用 module-aware 的 「 合约模式」 代替 「 插件模式 」 ,只是觉得这种模式非常好,业务根本没必要关系底层如何实现
打开 ( open ) 或 创建 ( create ) 或 打开即创建
本章节,我们继续学习 IndexedDB,使用 IndexedDB 前最终的一件事就是确保数据库是否存在。
当检查完数据库是否存在后,就两件事,存在则打开,不存在则创建。这个道理很简单,大家都懂。
很多有点古老的数据库,都为这两个操作提供了两套 API,而且打开一个数据库之前必须先用创建数据库的 API 创建。比如 MySQL 提供了 create database 语句用于创建数据库,而提供了 use 语句用于打开数据库
但是,一些最新的数据库系统,例如 MongoDB 和 Redis 则只提供了一套 API。即用于创建又用于打开,模式类似于 「 如果存在,则直接打开,不存在则先创建再打开 」
然后,你知道的,我们要讲解的 IndexedDB 也使用的是最新的这种 「 打开即创建 」 的方法
window.indexedDB.open()
window.indexedDB 提供了一个方法 open() 用于打开一个已经存在的数据库,并返回一个 IDBOpenDBRequest 的对象
indexedDB.open() 方法是异步的,永远都会返回一个 IDBOpenDBRequest 的对象
该方法的原型为
IDBOpenDBRequest open(database,version)
-
参数
database是一个字符串,指定了要打开的数据库名称。如果指定的数据库不存在,则默认会自动新创建一个,然后在打开 -
参数
version则是一个整数,用于指定要打开的数据库的版本。如果省略该参数,则会自动打开数据库的最新版本,如果数据库不存在,则默认值为1
indexedDB.open() 方法的返回值是一个 IDBOpenDBRequest 的实例。无论是否成功打开,返回的都是 IDBOpenDBRequest 的实例
范例
例如下面的语句,用于在当前域名下创建一个 IndexedDB 数据库 demo,并且使用默认的版本号 1
const req = window.indexedDB.open('demo'); console.log(req);
输出结果如下
IDBOpenDBRequest {onblocked: null, onupgradeneeded: null, result: IDBDatabase, error: null, source: null, …}
IDBOpenDBRequest
当我们展开 IDBOpenDBRequest 对象的实例 re1 时,可以看到该对象有以下属性和方法
IDBOpenDBRequest {
error:null,
onblocked : null,
onerror : null,
onsuccess : null,
onupgradeneeded : null
readyState: "done"
result : IDBDatabase {
name : "demo"
objectStoreNames :
DOMStringList {length: 0}
onabort :null
onclose :null
onerror :null
onversionchange :null
version :1
__proto__ : IDBDatabase
}
source : null,
transaction : null,
__proto__ : IDBOpenDBRequest
}
这个 IDBOpenDBRequest 真的是很简单,每个方法每个属性都简明扼要
其中最终要的是三个事件属性 error, success, upgradeneeded 分别用于在 打开失败或升级失败、打开成功 和 版本升级成功 后的回调
如果你熟悉 Node.js,你会对这种事件回调方法非常的熟悉
-
事件
error事件
error用于指定数据库打开失败或升级失败时候的回调函数,结合上面的req对象,使用方法一般如下request.onerror = function (event) { console.log('打开数据库失败'); }; -
事件
success事件
success用于指定数据库打开成功时候的回调函数,用法一般如下// 先指定一个全局的变量用于存储数据库对象实例 var db; req.onsuccess = function (event) { db = event.target.result; console.log('数据库成功打开'); };关于
event.target.result对象,我们稍后会学习到 -
事件
upgradeneeded如果
open()方法的参数version所指定的版本号大于数据库的实际版本号,则会发生数据库升级事件升级升级有可能成功,也有可能失败
但是,有一点很重要,就是如果检测到需要升级,那么会先升级,然后再打开
- 如果是失败则会触发事件
error - 如果成功,则会先触发
upgradeneeded然后再触发success - 如果版本号相同,则不会触发升级,也就不会触发升级事件
upgradeneeded
该事件的使用方法一般如下
request.onupgradeneeded = function (event) { let db2 = event.target.result; }注意:虽然
onupgradeneeded事件的参数event也会返回一个数据库对象IDBDatabase,但该对象只是表示升级成功的数据库对象,并不一定表示之后的打开操作中会一定成功。所以一般情况下,不建议将event.target.result赋值给全局数据库变量 - 如果是失败则会触发事件
范例
了解了这三个属性,现在我们就可以写一个完整的打开数据库的代码了
let db; const req = window.indexedDB.open('demo'); req.onerror = function (event) { console.log('打开数据库失败'); }; req.onsuccess = function (event) { db = event.target.result; console.log('打开数据库成功'); }; req.onupgradeneeded = function (event) { console.log(event.target); console.log('升级成功'); }
运行结果为
打开数据库成功
IDBDatabase 对象
我们可以看到,对于数据库升级成功和打开成功,都会返回一个 IDBDatabase 对象的实例,它表示的就是我们要打开的数据库,我们一起来看看这个数据库实例有什么属性吧
运行下面的代码
const req = window.indexedDB.open('demo',1);
req.onsuccess = function (event) {
console.log(event.target.result);
};
将输出结果展开后,得到
IDBDatabase {
name : "demo"
objectStoreNames :
DOMStringList {length: 0}
onabort :null
onclose :null
onerror :null
onversionchange :null
version :1
__proto__ : IDBDatabase
}
IDBDatabase 对象也有很多事件属性,但这些事件属性我们以后会介绍,我们就来看看对于数据库来说的两个最重要的属性
name : "demo"用于表示当前打开的或升级的数据库的名称version :1用于表示当前打开的或升级成功后的数据库的版本号
这两个属性,我们一般情况下会在 Web 开发过程中传回给服务器,用于服务器确定要如何升级
结束语
本章节的内容有点长,希望打开能消化得了。而对于我们未介绍的 IndexedDB 版本升级机制,我们将在下一章节中介绍