浏览器 IndexedDB 简明教程 ( 十一 ) - 读取所有数据

yufei       5 年, 8 月 前       1613

经过了第十章节 浏览器 IndexedDB 简明教程 ( 十 ) - 读取数据get() 方法,你可能会说,那么要怎么获取一个存储对象里的所有数据呢 ?

虽然 IDBObjectStore 提供了 getAll() 方法,但是好像该方法是在第二草案中出现,当前并没有得到良好的支持

难道没有其它办法了么?

答案是否定的,还有一个办法,叫做 「 遍历 」

游标 cursor

说起遍历数据,大家一定会想到什么 ? 比如下面的数据

1. 苹果
2. 香蕉
3. 梨
2. 香蕉
4. 桃

你怎么知道当前已经遍历到了哪条数据呢? 比如我们输出了 苹果 之后,要怎么知道下一个就是 香蕉 呢 ?

你肯定会说,我知道啊,因为刚刚我输出 苹果 的时候发现它的编号,我记得这个编号,那么下一个数据不就是把编号 +1 ,不就得到了 香蕉 的编号么 ?

对,你非常聪明

在我们编程中,我们把这种记住编号的方法叫做 「 游标 」 ( cursor )

IDBCursor

IndexedDB 中遍历数据也要记住,也要通过记住编号来获得,IndexedDB 中的 「 游标 」 是一个叫 IDBCursor 的对象

IDBCursor 也是一个异步操作集合

我们先来看看 IDBCursor 的对象提供了哪些方法和属性

IDBCursor 对象属性

属性 方法
cursor.source 只读,返回游标遍历的 IDBObjectStore 或 IDBIndex
cursor.direction 只读,游标遍历的方向
next: 从数据源开始位置遍历
nextunique: 从数据源开始位置开始遍历,当取值又重复时,只获取一次
prev: 从数据源的最后位置开始遍历
prevunique: 从数据源最后位置开始遍历,当取值又重复时,只获取一次
cursor.key 只读,返回游标所在位置处记录的键。如果游标超出范围,则返回 undefined
cursor.primaryKey 只读,返回游标当前位置的主键。如果游标当前正在迭代或超出迭代范围,则设置为undefined
游标的主键可以是任何数据类型

cursor.key 其实就是上面我们所说的编号,我们重点介绍下 cursor.direction

让我们再次回到上面举的遍历的例子,我们知道,遍历有两种方式

  1. 一种是顺着遍历,从头到尾,也就是 1 -> 2 -> 3 -> 2 -> 4,IndexedDB 把这种顺着遍历的方式称之为 `next

  2. 另一种是倒着遍历,从尾到头,也就是 4 -> 2 -> 3 -> 2 -> 1 ,IndexedDB 把这种遍历方式称之为 prev

而至于 nextuniqueprevunique 则是会排除重复值,比如两个 香蕉只取出现的第一个

IDBCursor 对象方法

方法 描述
cursor.advice(count) 游标移动的次数
cursor.continue(optional Key) 继续沿着当前游标遍历方向,找到下一个能够匹配 key 参数的键。如果没有指定参数,则根据游标当前遍历方向,移动到下一个位置
cursor.delete( ) 返回一个 IDBRequest 对象。在一个独立线程内删除游标所在位置处的记录(不移动游标),随后将游标设置为 null
cursor.update(newValue) 返回一个 IDBRequest 对象。在一个独立线程内,使用 newValue 来更新对象存储内游标当前位置处的值。如果游标指向的记录已被删除,则利用指定的 newValue 值创建一个新的记录

人如其名,方法名也是,我们重点介绍两个,剩下的我们会在后面的章节中提到

  1. cursor.continue(optional_key)

    该方法用于将游标移动到下一个位置,对于上面的范例来说,就是把编号 +1 或 -1 ( 取决于移动方向 cursor.direction ),如果指定了 key ,则会移动到下一个 key 的位置,那么移动距离可能就不是 +1 或 -1 了,而是 +3 +4 等

  2. cursor.advice(count)

    该方法会返回游标移动的次数,正常情况下,返回的值都是 1,因为不带参数的 cursor.continue 方法移动距离 如果给 cursor.continue 传递了一个 key,那么移动的距离可能就不是 1 了,而是这个操作移动的距离

游标实例

那么要怎么创建 IDBCursor 的实例呢? IDBCursor 没有提供相关的方法啊 !

是啊,IDBCursor 没有提供,但如果你回忆起了 存储对象 IDBObjectStore 就会想起它提供了 openCursor() 方法

IDBObjectStore.openCursor([range], [direction])

该返回 IDBRequest 对象,并在在一个独立的线程内,在对象存储的记录上创建一个游标

也就是说,我们的游标实例,是 IDBRequest.onsuccess 回调 event.target 对象

范例

下面的代码在 city 存储对象上创建一个游标,并遍历存储对象 city 中的所有数据

var db;

//先删除
window.indexedDB.deleteDatabase('demo')

var req = window.indexedDB.open('demo');

req.onerror = function (event) {
    console.log('打开数据库失败');
};

req.onsuccess = function (event) {
    console.log('打开数据库成功');
    db = event.target.result;
    var ts = db.transaction( ['city'] ,'readwrite' );
    var city_os = ts.objectStore('city')

    city_os.add({city_id:100000,'city_name':'北京'});
    city_os.add({city_id:300000,'city_name':'天津'});
    console.log('往 city 里添加了一条数据');

    var ts2 = db.transaction( ['city'] ,'readwrite' );
    var city_os2 = ts2.objectStore('city');
    // 在 city 存储对象上创建一个游标
    var req3 = city_os2.openCursor();
    req3.onsuccess = function (event) {
        var cursor = event.target.result;
        if (cursor) {
            console.log('city_id: ' + cursor.key);
            console.log('city_name: ' + cursor.value.city_name);
            cursor.continue();
        } else {
        console.log('No more data');
        }
    };
};

req.onupgradeneeded = function (event) {
    console.log('升级成功');
    db = event.target.result;
    db.createObjectStore('city',{keyPath:'city_id'});
}

输出结果如下

升级成功
打开数据库成功
往 city 里添加了一条数据
city_id: 100000
city_name: 北京
city_id: 300000
city_name: 天津
No more data
目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.