`
rainsilence
  • 浏览: 160763 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

HTML5之IndexedDB使用详解

阅读更多

 随着firefox4正式版的推出,IndexedDB正式进入我们的视线。IndexedDB是HTML5-WebStorage的重要一环,是一种轻量级NOSQL数据库。相较之下,WebDataBase标准已经很长时间没有更新,大有被IndexedDB取代的意思。

 

Section 1:起步,得到Database引用

w3c为IndexedDB定义了很多接口,其中Database对象被定义为IDBDataBase。而得到IDBDataBase用的是工厂方法,即从IDBFactory中取得。浏览器对象中,实现了IDBFactory的只有indexedDB这个实例。

大家可以先看下IDBFactory和IDBDataBase接口的定义

interface IDBFactory {
    IDBRequest open (in DOMString name);
    IDBRequest deleteDatabase (in DOMString name);
};

interface IDBDatabase : EventTarget {
    readonly attribute DOMString     name;
    readonly attribute DOMString     version;
    readonly attribute DOMStringList objectStoreNames;
    IDBObjectStore          createObjectStore (in DOMString name, in optional Object optionalParameters) raises (IDBDatabaseException);
    IDBRequest              deleteObjectStore (in DOMString name) raises (IDBDatabaseException);
    IDBVersionChangeRequest setVersion ([TreatNullAs=EmptyString] in DOMString version);
    IDBTransaction          transaction (in any storeNames, in optional unsigned short mode) raises (IDBDatabaseException);
    void                    close ();
             attribute Function      onabort;
             attribute Function      onerror;
             attribute Function      onversionchange;
};

interface IDBRequest : EventTarget {
    readonly attribute any            result get raises (IDBDatabaseException);
    readonly attribute unsigned short errorCode get raises (IDBDatabaseException);
    readonly attribute Object         source;
    readonly attribute IDBTransaction transaction;
    const unsigned short LOADING = 1;
    const unsigned short DONE = 2;
    readonly attribute unsigned short readyState;
             attribute Function       onsuccess;
             attribute Function       onerror;
};

 

重要:IndexedDB中,几乎所有的操作都是采用了command->request->result的方式。比如查询一条记录,返回一个request,在request的result中得到查询结果。又比如打开数据库,返回一个request,在request的result中得到返回的数据库引用。

 

从IDBFactory的方法体定义中可以看到,返回了一个IDBRequest对象。这个IDBRequest就是刚才所说的request。

 

下面给出一个通用的得到IDBDataBase的方法

 

if (!window.indexedDB) {
	window.indexedDB = window.mozIndexedDB || window.webkitIndexedDB;
}

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

request.onsuccess = function(e) {
	// Obtain IDBDatabase 
	// VERSION_CHANGE transaction callback
	var db = request.result;
}

 

Firefox4中使用IndexedDB的注意点:

1.indexedDB这个实例并不叫indexedDB,而是叫mozIndexedDB

2.indexedDB无法在iframe或者frame标签中使用

3.Firefox4中并未实现deleteDatabase方法(可能会在新版本中改进)

4.indexedDB.open并不能简单的看成是打开数据库,而是在打开数据库的基础上启动了一个version_change事件方法回调。在这个回调方法里自动启动了一个事务,用于version_change。IDBDatabase对象必须要在这个事务中才能取得。

 

 

Section 2:初始化object store

indexedDB标准建议,在初始化的时候创建表。以后每次打开浏览器,只需要check版本号。不需要第二次创建。而表在indexedDB中被称为object store。

下面给出object store接口的定义:

interface IDBObjectStore {
    readonly attribute DOMString      name;
    readonly attribute DOMString      keyPath;
    readonly attribute DOMStringList  indexNames;
    readonly attribute IDBTransaction transaction;
    IDBRequest put (in any value, in optional any key) raises (IDBDatabaseException, DOMException);
    IDBRequest add (in any value, in optional any key) raises (IDBDatabaseException, DOMException);
    IDBRequest delete (in any key) raises (IDBDatabaseException);
    IDBRequest get (in any key) raises (IDBDatabaseException);
    IDBRequest clear () raises (IDBDatabaseException);
    IDBRequest openCursor (in optional any range, in optional unsigned short direction) raises (IDBDatabaseException);
    IDBIndex   createIndex (in DOMString name, in DOMString keyPath, in optional Object optionalParameters) raises (IDBDatabaseException);
    IDBIndex   index (in DOMString name) raises (IDBDatabaseException);
    void       deleteIndex (in DOMString indexName) raises (IDBDatabaseException);
};
 

 

大家可以看到IDBDatabase中有一个createObjectStore方法。但是取得IDBDatabase后直接调用会报Exception。原因在于createObjectStore不能在version_change 的transaction callback中被调用。

 

下面给出通用的创建object store的代码

var db = null;
var customerData = [
		{ssn: "444-44-4444", name: "Bill", age: 25, email: "bill@company.com", nickName: ["1", "2", "3"]},
		{ssn: "555-55-5555", name: "Donna", age: 34, email: "donna@home.org"},
		{ssn: "666-66-6666", name: "Jack", age: 14, email: "jack@sina.com.cn"}
	];
request.onsuccess = function(e) {
	// Obtain IDBDatabase 
	// VERSION_CHANGE transaction callback
	db = request.result;
	
	if (db.version != "1.0") {
		var requestVersion = db.setVersion("1.0");
		requestVersion.onerror = function(event) {
			alert(event);
		}
		requestVersion.onsuccess = function(event) {
			createObjectStore(db);
		}
	}
	
	db.close();
};

function createObjectStore(db) {

	if (db.objectStoreNames.contains('customers')) {
		db.deleteObjectStore("customers")
	}
	// Create Object Store
	// This method was not called from a VERSION_CHANGE transaction callback.
	var objectStore = db.createObjectStore("customers", {
		// primary key
		keyPath: "ssn",
		// auto increment
		autoIncrement: false
	});
	
	objectStore.createIndex("name", "name", { unique: false });
	
	objectStore.createIndex("email", "email", { unique: true });
	
	// Add initial data
	for (var index = 0; index < customerData.length; index++) {
		objectStore.add(customerData[index]);
	}
}

 以上代码创建了一个名为customers,PrimaryKey为ssn,并且不带自增序列的object store(表)。并为这个object store创建了两个索引(name和email).其中email是唯一键。并且为customers创建了初始数据。可以看到初始数据中可以嵌套多层结构。

 

Section 3:事务和游标

通过上面IDBDatabase接口的定义,我们可以从IDBDatabase中取得transaction。在indexedDB中,事务会自动提交或回滚。所以无需手动commit或者rollback。

事务分为三种

IDBTransaction.READ_ONLY              只读

IDBTransaction.READ_WRITE            可读可写

IDBTransaction.VERSION_CHANGE    版本升级

我们用的最多的是前两种。如果不设置事务级别,则默认为READ_ONLY。

 

游标是遍历object store的唯一方法。虽然firefox4中有getAll,但是相信在不久的将来,这个方法会被取缔。

 

如果在打开游标的时候不设置,默认采用IDBCursor.NEXT

 

下面给出得到事务对象的通用方法

// 通过IDBDatabase得到IDBTransaction
var transaction = db.transaction(["customers"]);

// 通过IDBTransaction得到IDBObjectStore
var objectStore = transaction.objectStore("customers");

// 打开游标,遍历customers中所有数据
objectStore.openCursor().onsuccess = function(event) {
			
	var cursor = event.target.result;
			
	if (cursor) {
		var key = cursor.key;
		var rowData = cursor.value;
		alert(rowData.name);
		cursor.continue();
	}
}

 上面代码中使用了游标,这里要注意,在调用了cursor.continue之后,cursor会重新调用onsuccess句柄上的方法。所以,以上代码的onsuccess实际上被调用了3遍。至于openCursor的使用方法,下个Section中会有提到

 

Section 4:索引查询

section3中的objectStore.openCursor是根据keyPath去查询的。如果想通过某个索引去查询,可以用objectStore.index(索引名).openCursor去查询

 

1)openCursor的第一个参数为查询条件,他需要传入一个IDBKeyRange对象。

IDBKeyRange的创建方式有4种,都是调用了IDBKeyRange的静态方法。分别代表了4种不同类型的条件。

// 只取得当前索引的值为Bill的数据
IDBKeyRange.only("Bill");

// 只取得当前索引的值大于Bill,并且不包括Bill的数据
IDBKeyRange.lowerBound("Bill", true);

// 只取得当前索引的值小于Bill,并且包括Bill的数据
IDBKeyRange.upperBound("Bill", false);

// 取得当前索引的值介于Bill和Jack之间,并且包括Bill,但不包括Jack的数据
IDBKeyRange.bound("Bill", "Jack", false, true);

 2)openCursor的第二个参数为游标方向。有4种

IDBCursor.NEXT                                  顺序循环

IDBCursor.NEXT_NO_DUPLICATE        顺序循环不重复

IDBCursor.PREV                                  倒序循环

IDBCursor.PREV_NO_DUPLICATE        倒序循环不重复

 

例子:

var boundKeyRange = IDBKeyRange.upperBound("Jack", false);
objectStore.index("name").openCursor(boundKeyRange, IDBCursor.PREV_NO_DUPLICATE).onsuccess = function(event) {
		var cursor = event.target.result;
		
		if (!cursor) {
			return;
		}
		
		var rowData = cursor.value;
		
		alert(rowData.name);
		cursor.continue();
	};

 

完整实例请参考附件。注意,indexedDB必须要在发布环境(web容器)中才可以运行。

分享到:
评论
4 楼 sscsacdsadcsd 2015-10-09  
挺诡异的 
promise/A为什么能写的这么多出来
3 楼 zhanzhonggang 2014-03-13  
 
    if (db.version != "1.0") { 
        var requestVersion = db.setVersion("1.0"); 
        requestVersion.onerror = function(event) { 
            alert(event); 
        } 
        requestVersion.onsuccess = function(event) { 
            createObjectStore(db); 
        } 
    } 
     
    db.close();
db.version的初始本来就是1.一进来就是false,那么创建就永远不会执行了吧。
2 楼 achun 2012-11-25  
DOM-LEVEL-3-EVENTS
事件模型
1 楼 achun 2012-11-25  
唉,我费了整整一天的工费才弄明白
indexedDB 操作的关键.
indexedDB 没有连接这个概念,要想在浏览器的console下单条命令的调试那是不行的.
所有的操作都必须在一定的状态下进行,这些状态就是API中的
onsuccess
onupgradeneeded
onversionchange
...
这些状态回调方法.
on结束的时候也就失去了真实操作权(虽然已经生成的对象是完整的)
最开始不明白这个,结果一开始就死到这里了,控制台下调试了一天
最后通过看官方的 http://www.w3.org/TR/IndexedDB/#dfn-invalidstateerror
就突然明白了,网上介绍的资料不多,偶英文不过关,,,苦啊.....

相关推荐

    浏览器端indexeddb封装成更简洁易操作的接口

    "JavaScript开发-其它杂项" 的标签明确了这个话题属于JavaScript开发的范畴,特别是非主流或者不常见的部分,比如IndexedDB,它是HTML5的一个离线存储标准,不属于JavaScript的基本特性,因此被归类为“其它杂项”。...

    Dexie.js基本使用-前端大容量存储IndexedDB 的包装库,可运行代码

    然而,由于其复杂的API,直接使用IndexedDB可能会遇到一些挑战。Dexie.js的出现就是为了简化这个过程,使得开发者能够更加方便地在前端进行大容量数据的管理和操作。 **1. 安装与引入** 首先,你可以通过npm或者...

    IndexedDB详细demo

    **IndexedDB 详解** IndexedDB 是一种在浏览器中存储大量数据的离线存储技术,它为Web应用程序提供了数据库的功能。这个技术尤其适用于那些需要在本地存储大量结构化数据的应用,如离线阅读应用、Web邮件客户端或者...

    HTML5开发精要与实例详解 pdf

    例如,可能包括创建一个带有语义化结构的新闻网站、实现响应式布局、构建多媒体播放器、开发基于HTML5的游戏以及利用Web Storage和IndexedDB实现数据存储的案例。每个实例都旨在让读者亲手实践,从而更好地理解和...

    html5开发详解-PDF

    HTML5的离线存储特性,如Application Cache和IndexedDB,使得网页可以在用户离线时访问部分数据,提高了用户体验。Web Storage(包括localStorage和sessionStorage)则为浏览器提供了更大的本地数据存储空间。 六、...

    HTML5开发精要与实例详解

    5. **离线存储**:HTML5的`Application Cache`(应用缓存)和`IndexedDB`允许网页在离线状态下仍然可以访问部分数据,提高了Web应用的可用性。 6. **表单控件升级**:新的表单元素如`&lt;input type="date"&gt;`、`...

    html5简介和简单的使用方法

    ### HTML5简介与使用方法详解 #### 一、HTML5简介 HTML5是HyperText Markup Language第五版的简称,它是Web开发领域的一项重要标准。自从1999年12月发布HTML4.01之后,HTML5及其相关标准成为了推动Web标准化运动的...

    纸飞机HTML5游戏源码

    此外,利用HTML5的`localStorage`或`IndexedDB`可以进行本地数据存储,提高游戏的加载速度和用户体验。 六、优化与兼容性 尽管HTML5具有跨平台的特性,但不同浏览器对HTML5的支持程度不同,因此游戏开发需要考虑...

    捕鱼达人 HTML5源码

    7. **数据持久化**:通过Web Storage或IndexedDB实现玩家进度、金币等数据的本地存储。 【源码学习价值】 通过学习捕鱼达人的HTML5源码,开发者可以深入理解HTML5游戏开发的全过程,包括如何利用Canvas进行游戏...

    Web前端开发案例教程(HTML5+CSS3)(微课版)_PPT课件.zip

    2. 存储机制:HTML5的离线存储API(如Web Storage和IndexedDB)使得网站可以离线工作,提供更好的用户体验。 3. 语义化:HTML5强调语义化,通过更准确的标签来描述网页内容,提高可读性和可访问性。 二、CSS3详解 ...

    带音乐HTML5圣诞网站模板

    4. **离线存储**:HTML5的离线存储(Offline Storage)特性如Web Storage(包括localStorage和sessionStorage)和IndexedDB,可以缓存网站的部分数据,即使在离线状态下也能访问部分页面内容,这对于一个节日主题的...

    5个HTML5的常用本地存储方式详解与介绍

    IndexedDB是异步的,并且能够在复杂的Web应用中处理大量数据,是HTML5推荐的本地存储方案。IndexedDB同样支持索引和事务,使得数据操作更加高效和安全。 总结来说,随着HTML5的到来,我们拥有了更多样化的本地存储...

    跳跳狗HTML5游戏源码

    此外,HTML5的Web Storage和IndexedDB API提供了本地存储功能,使得游戏进度、用户数据得以保存,即使在离线状态下也能继续游戏。对于"跳跳狗"来说,可能使用这些API存储玩家的分数或者解锁成就。 Web Audio API是...

    微信HTML5在线朋友圈游戏源码带安装部署教程-飙车追妹子游戏.zip

    5. 存储管理:使用Web Storage或 indexedDB 存储用户的游戏数据。 四、安装部署教程 1. 准备环境:确保本地安装了Node.js和Git,用于搭建服务器和版本控制。 2. 下载源码:从提供的压缩包中解压,获取游戏源代码。 ...

    基于html5实现的拼图小游戏.zip

    HTML5的离线存储API(如Web Storage或IndexedDB)可以用来保存用户的游戏进度,以便用户离开后能继续游戏。 接着,CSS用于美化游戏界面,实现视觉效果。CSS3的动画和过渡效果可以用于拼图移动时的平滑过渡,以及...

    基于HTML5的聊天App.zip

    1. **离线存储(Offline Storage)**:HTML5的离线存储功能,如`Application Cache`和`IndexedDB`,使得聊天应用可以在离线状态下仍能访问部分数据,提高了用户体验。用户在网络不稳定或无网络时,仍能查看历史消息...

    Pro HTML5 Programming, 2nd Edition

    - **存储APIs**:包括Web Storage和IndexedDB在内的存储技术,使得网页可以在本地持久化数据,增强了离线访问能力。 - **离线Web应用程序**:HTML5支持创建离线可用的Web应用程序,即使在网络连接不可用时也能正常...

    神枪手HTML5游戏源码

    7. 数据持久化:HTML5的Web Storage(包括localStorage和sessionStorage)以及IndexedDB提供了本地数据存储能力,可以用来保存用户的游戏进度、设置等信息,使得游戏具有离线可用性。 8. 跨平台兼容:HTML5游戏的一...

    胸口碎大石HTML5游戏源码

    这可能涉及到HTTP/HTTPS请求、Web Storage(localStorage和sessionStorage)或IndexedDB等技术来实现客户端与服务器的数据交换。 【测试与使用】: 在实际使用前,开发者或使用者需要将源码部署到支持HTTP或HTTPS...

Global site tag (gtag.js) - Google Analytics