IndexedDB是可以让您在浏览器中持久保存数据的一种方法。不管网络是否可用,它都可以让您创建带有强大的数据查询能力的web应用,这些应用可以是联网的、或者离线的。IndexedDB 适用于存储大量数据的应用(比如dvd碟片出租库的登记簿)和不需要持久连网运行的应用(比如,邮件客户端、待办事项、注释板)
关于
本文档讨论IndexedDB的核心概念和术语。将为你展示重点并解释关键的概念
下面是一些有用的提示信息:
如需学习更多的IndexedDB 术语,请参考Definitionssection(定义章节).
如需获取怎样使用IndexedDB API的详细例子,请参考UsingIndexedDB(使用IndexedDB)
如需IndexedDB API参考文档,请返回主页面,参考IndexedDBAPI文章和它的子标题部分,该文档记录了IndexedDB的对象类型。如需更多关于浏览器如何存储数据的知识,请参考Browser storage limits and eviction criteria(浏览器存储限制和回收策略)。
IndexedDB总览
IndexedDB 让您使用key(键)作为索引来存储和检索对象。您对数据库所做的所有更改都发生在transactions(事物)中。就像其它多数的web存储方案一样,IndexedDB 遵循same-originpolicy(同源策略)。因此,您可以访问自己同一域的数据,但是无法访问其它域的数据。
IndexedDB 是asynchronous(异步)的API,可以应用于大多数环境中,包括WebWorkers(一种在后台执行js脚本的策略)。它页也曾经有一个synchronous(同步)的版本,应用于WebWorkers,但是由于广大的web开发者对其并不热衷,因此已经被去除了。
IndexedDB曾经有一个竞争对手,Websql ,但是官方组织W3C 在2010年11月18日宣布不在支持它了。虽然两个数据库都用于存储前端数据,但是他们具有不同的实现机制,Websql 是一个关系型数据库,IndexedDB是一个索引型数据库。
重点概念
如果您已经习惯了其它类型的数据库,那么可能无法快速适应IndexedDB因此,请牢记以下几个重要的概念:
IndexedDB 数据库存储【键-值】对。【值】可以是复杂结构的对象,【键】可以是这些对象的属性。您可以基于这些对象的属性,为快速查询创建索引,也可以存储详表
(此处翻译不了,见谅)。【键】也可以是二进制对象。
IndexedDB基于事务数据库模型。您对IndexedDB所做的所有操作都发生在一个事务环境中。IndexedDB API提供了一系列对象比如indexes,tables,cursors,等等,但是
每一个对象都需要绑定到特定的事务。因此,您不能在事务之外执行指令或者打开游标。事务有明确的生存周期,因此,如果您试图在事务结束之后使用它,将引发异常。
而且,事务是自动提交的,不能被手动提交。
当您在考虑以下操作会导致什么样的结果时,事务数据模型是很有用的:用户在两个不同的标签页分别打开了同一个web应用的实例。如果没有事务操作,两个实例可以相
互干扰对方的修改。
如果您不熟悉数据库的事务操作,请参考Wikipedia article on transactions。还有【定义】一节的 transaction。
IndexedDB API几乎都是异步的。这些API 不直接通过返回值把数据传递给您;相反的,您必须提供一个回调函数。您不是(通过同步方式)【存储】或者【查询】一个【值】到(从)数据库中,相反,您应该向数据库请求一个操作,在那个操作完成时,您将得到一个DOM事件,该事件的类型值使您能够判断该操作是成功或者失败。这听起来有点复杂,但是,这是有健全的处理机制的。这种工作方式与XMLHttpRequest 并无不同。
IndexedDB 使用了大量的【请求】。【请求】是一些对象,他们负责接接收表示成功或者失败信息的DOM事件(前面提到)。他们拥有onsuccess和onerror 属性,而且你可
以使用对他们使用addEventListener(), removeEventListener()。他们也拥有readyState,result,和errorCode 属性用于告知【请求】的状态。result属性非常地神奇,因为
它可以表示许多不同的东西,这取决于请求的方式(比如,可以是IDBCursor 实例,或者是您刚插入的数据记录的键)。
IndexedDB使用DOM 事件通知您什么时候结果是有效的。DOM事件总是具有一个【type】属性值(在IndexedDB中,它通常是success或者error)。DOM事件也有一个【target】属性,用以标示事件发生的目标。多数情况下,事件的target属性是一个IDBRequest对象,以作为一个数据库操作的结果。成功事件不会冒泡而且他们不能被取消。对于错误事件,要冒泡,而且可以被取消。这一点是很重要的,因为错误事件一定要取消,无论它们运行在什么事务中,除非它们被取消了。
IndexedDB 是面向对象的。IndexedDB不是使用table【表】来表示行与列的关系型数据库,这个重要的基本的不同点
影响了您设计和创建应用的方式。
在传统的关系数据存储中,您将使用一个表来存储数据集,其中行存储了记录、列存储了字段名。在IndexedDB中,相反的,需要您为一个数据类型创建一个对象store,同
时为对象store简单地持久化javascript对象。每个对象store可以有一个带索引的数据集,索引使之能够查询和迭代遍历。如果您还不熟悉面向对象的数据库管理系统,请参照Wikipedia article on objectdatabase.
IndexedDB不使用结构化查询语言(sql)。而是使用基于索引的查询,该查询会产生一个游标,用以让您迭代遍历结果集。如果您还不熟悉非结构化(Nosql),请参照Wikipediaarticle on Nosql.
IndexedDB坚持遵循同源策略。源是指——域,应用层协议,和脚本将要执行的目标文件的URL的端口号。每个源都有自己关联的数据库集和,每个数据库都有能表示所在源的名字。
安全边界使得IndexedDB阻止web应用访问不同的域。比如,一个在http://www.example.com/app/的应用能访问ttp://www.example.com/dir/的内容,因为他们所处同一个域中,但是不能访问http://www.example.com:8080/dir/(不同的端口),因为他们所处不同的域中。
Definitions
本节定义和解释了IndexedDB API中用到的术语
database
信息仓库, 通常包括一个或者多个对象stores。每个数据库必须包含如下内容:
名字name:标识了一个在特定的源中的数据库,该数据库在它的生存周期内保持恒久不变。名字可以是任意字符串,(包含空字符串)。
当前版本:当一个数据库首次被创建时,(如果没有被特别指定)它的版本号是整数1。每个数据库在任意时刻只能有一个版本号。
durable
对于FireFox浏览器,IndexedDB是数据持久的,意味着在读写事务中,IDBTransaction.oncomplete唯一被触发的
条件就是确保所有数据已经写入磁盘。
从Firefox 40起,IndexedDB事务为改善性能放宽了durable(数据持久性保证),在其它的IndexedDB支持的浏览器中也是如此。在这种情况下,当操作系统被告知要写入数据,但是实际上数据还没有真正写入磁盘的时候,【complete】事件就被触发。这样,事件触发当然要比以前快,然而,存在一个漏洞,如果在数据完全写入磁盘之前,操作系统崩溃或者系统掉电,整个事务将会丢失。因为这种灾难事件极少,所以大多数用户不需要担心这些。
object store
根据这种机制数据被存入数据库。对象store持久的保存了【键-值对】记录。对象store中的记录按照【键】升序排列
每个对象store必须有一个名字在数据库中唯一表示。对象store可以选择性的拥有一个【键】生成器和一个【键】路径。
如果对象store拥有一个【键】路径,则使用行内【键】;否则,使用行外【键】
更多关于object store的文档,请参考IDBObjectStoreor IDBObjectStoreSync.
version
数据库首次创建时,版本号是整数1,。每个数据库每次只能有一个版本号;同一数据库不能同时拥有多个版本号。
变更版本号的唯一方法是以更高版本号打开它。这将开启一个versionchange事务,并且触发upgradeneeded事件。
唯一能够更新数据库的schema的地方就是在事件句柄中。
注意: 此定义描述了最新的规范,这些规范只在最新的浏览器中支持。旧版本的浏览器支持的IDBDatabase.setVersion()
方法已经被废除了。
database connection
打开数据库时创建的一个操作(connections),一个给定的数据库可以同时有多个connections
transaction
对指定数据库的数据访问和数据更新的原子操作集合。它描述了你应该如何操作数据。实际上,任何读取和更新的数据操作必须在事务中执行.
数据链接connection 可以同时拥有多个活动的事务,只要【写】事务没有重叠的作用域(scope)。在创建事务时定义的作用域,决定了事务可以与哪个对象store发生关系,并
使之(对象store)在事务剩余的生存周期内保持稳定。因此,如果某一个数据连接已经拥有一个【写】事务,该事务的作用域涵盖了flyingMonkey对象store,您可以开启第
二个事务并且该事务带有作用域涵盖了unicornCentaur 和unicornPegasus对象 stores。对于【读】事务类型,您可以拥有多个,甚至是作用域重叠的。
事务的生存周期应该很短,如果一个事务占用了太长时间,浏览器可以结束它,从而释放被它占用的存储资源。您可以中止事务,从而回滚事务对数据库的数据变更。而且,
您甚至不需要等待事务开启或者激活,就可以中止它。
IndexedDB的三种事务模式:readwrite,readonly,和versionchange。创建和删除对象stores和indexes只能使用
versionchange事务。如需学习更多的事务类型,请参考IndexedDB文档。
所有的东西都发生在事务中,这一点非常重要。如需学习更多的关于事务的知识,尤其是如何关联版本,请参考
IDBTransaction,,它也有专门的文档描述。 如需学习同步API, 请参考IDBTransactionSync.
Request
一种操作,用以在数据库上执行的读写行为。每一个Request代表了读或者写。
Index
Index是一个专门的对象store,用以查询存储在另一个对象store中的记录,另一个对象store也被称为被索引的对象store。Index是一个持久的【键-值】记录集合,记录的【值】是被索引对
象store的【键】。
(举例如下:对象store:objStore1;存储数据:{name:nancy;age:28}. Index:objStore2;存储数据:{item1:name; item2:age })
当被索引对象有新纪录插入、更新、删除时,Index中的记录自动填充。Index中的每一条记录只能指向一条被索引对象
的记录,但是Index中的多条记录可以指向同一条被索引对象的记录。当被索引对象发生变化时,所有相关的index记录自动更新。或者,您也可以(直接)使用【key】在对
象store中查询记录。(这里的【key】就是该对象store中【键-值】对记录中的【键】)。
如需学习更多如何使用Index,请参考 UsingIndexedDB. 如需Index文档,请参考IDBKeyRange.
Key and value
key
【键】是一个数据值,被用来在对象store中组织和查询存储的记录。对象store可以从以下三个来源获取【键】:
键生成器key generator、键路径keypath、或者明确指定【键】的值。【键】含有的整型值比它前面的【键】(的值)大。
对象store的每条记录必须含有一个唯一键,所以您不能让多条记录公用同一个【键】。
【键】可以是以下类型的一种:string,date,float,a binary blob,andarray。对于数组,【键】的取值可以从空到无穷,
而且您可以在数组中包含另一个数组。或者,您可以使用index对象来查询对象store中的记录数据。
key generator
一种按照队列顺序生成新【键】的机制。如果对象store没有键生成器,应用程序必须为简要存入的记录提供【键】。
生成器不能在对象store之间共享。这是在浏览器内部实现的,因为在web开发中,您确实不能创建或者访问【键】生成器
in-line key
行内【键】作为数据记录的一部分存储在对象store中。可以通过keypath找到它。行内【键】可以由生成器创建。
行内【键】创建以后,可以通过key path向其中存储值,或者也能(直接)作为【键】使用
out-of-line key
独立于对象store中的记录的【键】
key path
规定了了浏览器应该从对象store抽取【键】或者从index获取【键】。一个有效key path应该包含下列内容的一项:
空字符串,javascript标识符,多个有句号分隔的javascript标识符或者包含它们任意一项的数组。但是,不能包含空格。
每条记录都有一个值,该值能够包含任何能用javascript表达的内容,比如boolean,number,string,object,array,regexp,undefined,和 null。当对象或者数组被存储时,它的属性和值可以是任意的有效值。Blobs 和 files类型可以被存储。可参考specification .
范围和作用域
作用域
事务应用的目标场合,是对象store和index的集合。【只读】事务可以同时执行重叠的作用域。相反,【写】事务的作用域是不能重叠的。您仍然可以同时开启多个活动的事务,但是它们必须排队等候,依次执行。
游标
一种机制,根据【键】的范围,迭代遍历多条记录。游标的【源】表示正在遍历哪个index或者对象store。游标在【键】的范围内有起始位置,可以按照升序或者降序移动。
有关更多的游标知识,请参考 IDBCursor 或者IDBCursorSync
【键】的范围
适用于【键】的指定数据类型的连续区间。可以通过【键】或者【键】的范围查询对象store或者index中的记录。
您可以适用上限、下限来限制或者过滤【键】的范围。比如,您可以在介于【x,y】之间的【键】的范围内迭代遍历所有结果。
IndexedDB 的设计涵盖了多数需要客户端存储的情形。但是,以下情况例外:
国际化Synchronizing。不是所有的语言排序都适用同一种方式,因此IndexedDB不支持国际化排序。虽然数据库不支持国际化排序,您可以把数据读出数据库之后,自己处
理国际化排序问题。注意,本地化自动识别排序已经从Firefox 43尝试支持了(只有firefox)。
同步Synchronizing。API不是被设计用来与服务端数据库的同步。如果您由此需求,必须自行设计程序。
完全匹配查询Full text searching。API不支持类似于sql中LIKE操作符的功能。
还有,小心浏览器会擦除整个数据库,例如以下的情况:
1用户请求了擦除操作。很多浏览器提供了设置选项,让用户能够清空指定网站的所有记录,包括cookies,书签,密码和IndexedDB数据
2浏览器在私密模式。一些浏览器有私密模式(Firefox)或者匿名模式(Firefox),结束会话之后,浏览器会删除数据库数据
3硬盘或者配额(存储限制)已经达到上限。
4数据出错。
5不兼容的设置变更。
时过境迁,浏览器的能力的已经发生变化,但是生产商却竭力让浏览器保持那些数据(抱歉。此处很别扭)