虚位以待(AD)
虚位以待(AD)
首页 > 网页特效 > HTML5 > HTML5新特性之客户端数据库(IndexedDB)

HTML5新特性之客户端数据库(IndexedDB)
类别:HTML5   作者:码皇   来源:u013084331的博客     点击:

1、简述 在HTML5本地存储——Web SQL Database提到过Web SQL Database实际上已经被废弃(由于至今Firefox和IE不支持),而HTML5的支持的本地存储实际上变成了Web Storage(Local Storage和Session S

 

1、简述

在HTML5本地存储——Web SQL Database提到过Web SQL Database实际上已经被废弃(由于至今Firefox和IE不支持),而HTML5的支持的本地存储实际上变成了Web Storage(Local Storage和Session Storage)与IndexedDB。Web Storage使用简单字符串键值对在本地存储数据,方便灵活,但是对于大量结构化数据存储力不从心,IndexedDB是为了能够在客户端存储大量的结构化数据,并且使用索引高效检索的API。

2、基本特性

(1).IndexedDB是对象数据库,即NoSQL(Not Only SQL),他比支持SQL查询的数据库简单多,但是,他要比Web存储API支持的键/值对存储更加强大、更高效、更健壮。

(2).IndexedDB与Web存储和文件系统API一样,IndexedDB数据库同样受同源政策的限制(即跨域问题),也就是说两个同源的Web页面相互之间可以访问对方的数据,但是非同源的页面是无法进行访问。

(3).IndexedDB的每个源都可以有任意数目的IndexedDB数据库。但是每个数据库的名字在该源下必须是唯一的,在IndexDB API中,一个数据库其实就是一个命名的对象存储区间(Object store)的集合。

(4). NoSQL的简介:

NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"。
在现代的计算系统上每天网络上都会产生庞大的数据量。
这些数据有很大一部分是由关系数据库管理系统(RDMBSs)来处理。 1970年 E.F.Codd's提出的关系模型的论文 "A relational model of data

for large shared data banks",

这使得数据建模和应用程序编程更加简单。
通过应用实践证明,关系模型是非常适合于客户服务器编程,远远超出预期的利益,今天它是结构化数据存储在网络和商务应用的主导技术。
NoSQL 是一项全新的数据库革命性运动,早期就有人提出,发展至2009年趋势越发高涨。NoSQL的拥护者们提倡运用非关系型的数据存储,

相对于铺天盖地的关系型数据库运用,这一概念无疑是一种全新的思维的注入。

(5).关系型数据库遵循ACID规则

5-1:A (Atomicity) 原子性
原子性很容易理解,也就是说事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功,只要有一个操作失败,整个事务就失败,需要回滚。
比如银行转账,从A账户转100元至B账户,分为两个步骤:1)从A账户取100元;2)存入100元至B账户。这两步要么一起完成,要么一起不完成,如果只完成第一步,第二步失败,钱会莫名其妙少了100元。
5-2:C (Consistency) 一致性
一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务的运行不会改变数据库原本的一致性约束。
例如现有完整性约束a+b=10,如果一个事务改变了a,那么必须得改变b,使得事务结束后依然满足a+b=10,否则事务失败。
5-3:I (Isolation) 独立性
所谓的独立性是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。
比如现有有个交易是从A账户转100元至B账户,在这个交易还未完成的情况下,如果此时B查询自己的账户,是看不到新增加的100元的。
5-4.D (Durability) 持久性
持久性是指一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。

3、异步API使用:

在IndexedDB大部分操作并不是我们常用的调用方法,返回结果的模式,而是请求——响应的模式,比如打开数据库的操作:

 

    var request=window.indexedDB.open('
    testDB'
    );
这条指令并不会返回一个DB对象的句柄,我们得到的是一个IDBOpenDBRequest对象,而我们希望得到的DB对象在其result属性中:

 

 

这条指令请求的响应是一个 IDBDatabase对象,这就是IndexedDB对象:

 

 

除了result,IDBOpenDBRequest接口定义了几个重要属性:

onerror: 请求失败的回调函数句柄

onsuccess:请求成功的回调函数句柄

onupgradeneeded:请求数据库版本变化句柄

所谓异步API是指并不是这条指令执行完毕,我们就可以使用request.result来获取indexedDB对象了,就像使用ajax一样,语句执行完并不代表已经获取到了对象,

所以我们一般在其回调函数中处理。

4.创建数据库

刚才的语句已经展示了如何打开一个indexedDB数据库,调用indexedDB.open方法就可以创建或者打开一个indexedDB。看一个完整的处理:

 

    function openDB (name) {
    var request=window.indexedDB.open(name);
    request.onerror=function(e){
    console.log('
    OPen Error!'
    );
    }
    ;
    request.onsuccess=function(e){
    myDB.db=e.target.result;
    }
    ;
    }
    var myDB={
    name:'
    test'
    , version:1, db:null }
    ;
    openDB(myDB.name);
5.version

 

我们注意到除了onerror和onsuccess,IDBOpenDBRequest还有一个类似回调函数句柄——onupgradeneeded。这个句柄在我们请求打开的数据库的版本号

和已经存在的数据库版本号不一致的时候调用。

indexedDB.open()方法还有第二个可选参数,数据库版本号,数据库创建的时候默认版本号为1,当我们传入的版本号和数据库当前版本号不一致的时候

onupgradeneeded就会被调用,当然我们不能试图打开比当前数据库版本低的version,否则调用的就是onerror了,修改一下刚才例子:

 

    function openDB (name,version) {
    var version=version || 1;
    var request=window.indexedDB.open(name,version);
    request.onerror=function(e){
    console.log(e.currentTarget.error.message);
    }
    ;
    request.onsuccess=function(e){
    myDB.db=e.target.result;
    }
    ;
    request.onupgradeneeded=function(e){
    console.log('
    DB version changed to '
    +version);
    }
    ;
    }
    var myDB={
    name:'
    test'
    , version:3, db:null }
    ;
    openDB(myDB.name,myDB.version);
由于刚才已经创建了版本为1的数据库,打开版本为3的时候,会在控制台输出:DB version changed to 3

 

5.关闭与删除数据库

关闭数据库可以直接调用数据库对象的close方法:

 

    function closeDB(db){
    db.close();
    }
删除数据库使用indexedDB对象的deleteDatabase方法:

 

 

    function deleteDB(name){
    indexedDB.deleteDatabase(name);
    }
简单的使用:

 

 

    var myDB={
    name:'
    test'
    , version:3, db:null }
    ;
    openDB(myDB.name,myDB.version);
    setTimeout(function(){
    closeDB(myDB.db);
    deleteDB(myDB.name);
    }
    ,500);
由于异步API愿意,不能保证能够在closeDB方法调用前获取db对象(实际上获取db对象也比执行一条语句慢得多),

 

所以用了setTimeout延迟了一下。当然我们注意到每个indexedDB实例都有onclose回调函数句柄,用以数据库关闭的时候处理,

有兴趣同学可以试试,原理很简单,不演示了。

6.object store

有了数据库后我们自然希望创建一个表用来存储数据,但indexedDB中没有表的概念,而是objectStore,一个数据库中可以包含多个objectStore,

objectStore是一个灵活的数据结构,可以存放多种类型数据。也就是说一个objectStore相当于一张表,里面存储的每条数据和一个键相关联。

我们可以使用每条记录中的某个指定字段作为键值(keyPath),也可以使用自动生成的递增数字作为键值(keyGenerator),也可以不指定。

选择键的类型不同,objectStore可以存储的数据结构也有差异.

键类型 存储类型
不使用 任意值,但是没添加一条数据的时候需要指定键参数
keyPath Javascript对象,对象必须有一属性作为键值
keyGenerator 任意值
都使用 Javascript对象,如果对象中有keyPath指定的属性则不生成新的键值,如果没有自动生成递增键值,填充keyPath指定属性

 

7.事务:

在对新数据库做任何事情之前,需要开始一个事务。事务中需要指定该事务跨越哪些object store。

事务具有三种模式

1.只读:read,不能修改数据库数据,可以并发执行
2.读写:readwrite,可以进行读写操作
3.版本变更:verionchange

 

    var transaction=db.transaction(['
    students'
    ,'
    taecher'
    ]);
    //打开一个事务,使用students 和teacher object storevar objectStore=transaction.objectStore('
    students'
    );
    //获取students object store

8.给object store添加数据

 

调用数据库实例的createObjectStore方法可以创建object store,方法有两个参数:store name和键类型。调用store的add方法添加数据。

有了上面知识,我们可以向object store内添加数据了.

keyPath:

因为对新数据的操作都需要在transaction中进行,而transaction又要求指定object store,所以我们只能在创建数据库的时候初始化

object store以供后面使用,这正是onupgradeneeded的一个重要作用,修改一下之前代码:

 

    function openDB (name,version) {
    var version=version || 1;
    var request=window.indexedDB.open(name,version);
    request.onerror=function(e){
    console.log(e.currentTarget.error.message);
    }
    ;
    request.onsuccess=function(e){
    myDB.db=e.target.result;
    }
    ;
    request.onupgradeneeded=function(e){
    var db=e.target.result;
    if(!db.objectStoreNames.contains('
    students'
    )){
    db.createObjectStore('
    students'
    ,{
    keyPath:"id"}
    );
    }
    console.log('
    DB version changed to '
    +version);
    }
    ;
    }
这样在创建数据库的时候我们就为其添加了一个名为students的object store,准备一些数据以供添加:

 

 

    var students=[{
    id:1001, name:"Byron", age:24 }
    ,{
    id:1002, name:"Frank", age:30 }
    ,{
    id:1003, name:"Aaron", age:26 }
    ];
    function addData(db,storeName){
    var transaction=db.transaction(storeName,'
    readwrite'
    );
    var store=transaction.objectStore(storeName);
    for(var i=0;
    ii++){
    pre="">

     

    这样我们就在students object store里添加了三条记录,以id为键,在chrome控制台看看效果:

    9.查找数据

    可以调用object store的get方法通过键获取数据,以使用keyPath做键为例:

     

      function getDataByKey(db,storeName,value){
      var transaction=db.transaction(storeName,'
      readwrite'
      );
      var store=transaction.objectStore(storeName);
      var request=store.get(value);
      request.onsuccess=function(e){
      var student=e.target.result;
      console.log(student.name);
      }
      ;
      }
10.更新数据

 

可以调用object store的put方法更新数据,会自动替换键值相同的记录,达到更新目的,没有相同的则添加,以使用keyPath做键为例

 

    function updateDataByKey(db,storeName,value){
    var transaction=db.transaction(storeName,'
    readwrite'
    );
    var store=transaction.objectStore(storeName);
    var request=store.get(value);
    request.onsuccess=function(e){
    var student=e.target.result;
    student.age=35;
    store.put(student);
    }
    ;
    }
11.删除数据及object store

 

调用object store的delete方法根据键值删除记录

 

    function deleteDataByKey(db,storeName,value){
    var transaction=db.transaction(storeName,'
    readwrite'
    );
    var store=transaction.objectStore(storeName);
    store.delete(value);
    }
调用object store的clear方法可以清空object store

 

 

    function clearObjectStore(db,storeName){
    var transaction=db.transaction(storeName,'
    readwrite'
    );
    var store=transaction.objectStore(storeName);
    store.clear();
    }
调用数据库实例的deleteObjectStore方法可以删除一个object store,这个就得在onupgradeneeded里面调用了

 

 

    if(db.objectStoreNames.contains('
    students'
    )){
    db.deleteObjectStore('
    students'
    );
    }
最后:

 

这就是关于indexedDB的基本使用方式,很多同学看了会觉得很鸡肋,和我们正常自己定义个对象使用没什么区别,也就是能保存在本地罢了,这是因为我们还没有介绍indexedDB之所以称为indexed的杀器——索引,这个才是让indexedDB大显神通的东西,下篇我们就来看看这个杀器。

 

相关热词搜索: