美文网首页
webDB简介与使用

webDB简介与使用

作者: 绝尘kinoko | 来源:发表于2022-03-31 10:34 被阅读0次

简介及应用场景

浏览器的大数据量存储方式,相当于数据库,webSql为关系型DB,indexDB为非关系型DB。

应用场景:

1、离线存储(C端应用)

2、富文本编辑,缓存记录,防止关闭标签页丢失数据。

浏览器支持:

/ Chrome IE Firefox
webSql 1 0 0
indexDB 1 0 1

Web Sql DataBase

w3c:https://www.w3.org/TR/webdatabase/

使用Sqlite方言,目前规范停滞。

刷新后库删除。

主要方法

1. window.openDatabase:使用现有的数据库或者新建的数据库创建一个数据库对象。

2. Database transaction:控制一个事务,以及基于这种情况执行提交或者回滚。

3. SQLTransaction executeSql:用于执行实际的 SQL 查询。

  • openDatabase()

openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024)

方法对应的五个参数说明:

1. 数据库名称

2. 版本号

3. 描述文本

4. 数据库大小

5. 创建回调

  • db.transaction()

参数有三

1. 事务内容方法

2. 事务失败方法

3. 事务成功方法


db.transaction((transaction) => {

    transaction.executeSql('...')  

    ...  

}, errorCb, successCb)

重点:

1. 只有executeSql抛出异常才会被transaction捕获;

2. 若executeSql已对异常进行处理(不throw),transaction则认为事务成功;

3. executeSql无失败回调默认视为抛出异常。

  • transaction.executeSql()

方法参数:sql语句、values参数(数组)、成功回调(参数:SQLTransaction,SQLResultSet)、失败回调(参数:SQLTransaction,SQLError)

0. 建表

transaction.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)')

1. 增

由于新增重复ID会中断事务,所以在新增时最好加上失败回调,错误处理(不throw就可以)

transaction.executeSql('INSERT INTO LOGS (id,log) VALUES (1, "...")')

或者使用插值,以下其他操作同理

transaction.executeSql('INSERT INTO LOGS (id, field) VALUES (?, ?)', [id_value, field_value])

成功回调SQLResultSet,主要返回为rowsAffected,表示影响行数

2. 删

sql语句正常时(指语法无误)无失败情况

transaction.executeSql('DELETE FROM LOGS WHERE id=1')

成功回调SQLResultSet,主要返回为rowsAffected,表示影响行数

3. 改

sql语句正常时无失败情况

transaction.executeSql("UPDATE LOGS SET log='...' WHERE id=2")

成功回调SQLResultSet,主要返回为rowsAffected,表示影响行数

4. 查

sql语句正常时无失败情况

transaction.executeSql("SELECT * FROM LOGS")

成功回调SQLResultSet,主要返回为rows:Array<SQLResultSetRow>,表示查询结果

indexDB

IndexedDB (后简称IDB)具有以下特点。

(1)键值对储存。 IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。

(2)异步。 IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。

(3)支持事务。 IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。

(4)同源限制 IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。

(5)储存空间大 IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。

(6)支持二进制储存。 IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。

刷新后不会重置DB。

使用步骤:

1. 打开数据库

let request = indexedDB.open('test', 2) IDBRequest

打开操作有4种结果——onsuccess, onerror, onupgradeneeded, onblocked,重点就是成功和升级

在成功时拿到数据库对象


let db

request.onsuccess = function(e) {

  db = request.result

}

如果是第一次打开数据库,会经历一次升级;升级的触发条件是数据库版本发生改变时,第一次打开的时候可以看作是从0到1,所以会触发,另外数据表的新建也要在这个阶段进行,而不是在success阶段。

2. 创建数据表

IDB的数据表类型为IDBObjectStore,为与其他sql类比,统称为数据表


let objectStore;

if (!db.objectStoreNames.contains('person')) {

    objectStore = db.createObjectStore('person', { keyPath: 'id', autoIncrement: true });

    objectStore.createIndex('name', 'name', { unique: false });

    objectStore.createIndex('email', 'email', { unique: true });

}

上面这段代码进行了以下操作:

1. 判定表集合有无目标表名称(person)
2. 如无目标表则创建该表,并指定主键及自增
3. 创建表索引——name和email,其中email字段要求唯一,同主键

3. 具体操作

IDB通过事务的方式操作数据表,不过IDB的transaction不是在内部通过执行sql作为回调的形式,而是链式调用objectStore方式拿到表进行操作


function getObjectStore(name) {

    return db.transaction([name], 'readwrite').objectStore(name);

}

拿到表后,进行操作会返回IDBRequest,由于操作是异步的,所以只能通过监听IDBRequest的状态来判断操作是否成功


<button onclick="clearTable()">清空表</button>
    <button onclick="queryAll()">查询整表</button>
    <button onclick="clearLog()">清空记录</button>
    <button onclick="test()">test</button>
    <p>增</p>
    <label for="name">name</label>
    <input type="text" id="name" />
    <label for="age">age</label>
    <input type="text" id="age" />
    <label for="email">email</label>
    <input type="text" id="email" />
    <button onclick="insert()">插入</button>
    <p>删</p>
    <label for="delId">id</label>
    <input type="text" id="delId" />
    <button onclick="deleteById()">删除</button>
    <p>改</p>
    <label for="updateId">id</label>
    <input type="text" id="updateId" />
    <label for="updateName">name</label>
    <input type="text" id="updateName" />
    <label for="updateAge">age</label>
    <input type="text" id="updateAge" />
    <label for="updateEmail">email</label>
    <input type="text" id="updateEmail" />
    <button onclick="update()">修改</button>
    <p>查</p>
    <label for="queryId">id</label>
    <input type="text" id="queryId" />
    <button onclick="queryById()">按id查</button>
    <input type="radio" name="index" id="indexName" value="name" checked />name <input type="radio" name="index" id="indexEmail" value="email" />email
    <input type="text" id="index" />
    <button onclick="queryByIndex()">按索引查</button>
    <p id="record"></p>
    <div id="all"></div>
    <script>
        let db;
        let request = indexedDB.open('test');
        request.onerror = function (e) {
            console.log('error...');
        };
        request.onsuccess = function (e) {
            console.log('success...');
            db = request.result;
        };
        request.onupgradeneeded = function (e) {
            console.log('upgrade...');
            db = e.target.result;
            let objectStore;
            if (!db.objectStoreNames.contains('person')) {
                objectStore = db.createObjectStore('person', { keyPath: 'id', autoIncrement: true });
                objectStore.createIndex('name', 'name', { unique: false });
                objectStore.createIndex('email', 'email', { unique: true });
            }
        };
        request.onblocked = function (e) {
            console.log('blocked...');
        };

        // utils
        function getObjectStore(name) {
            return db.transaction([name], 'readwrite').objectStore(name);
        }

        function transaction(request, success, error) {
            request.onsuccess = function (e) {
                success(e);
            };
            request.onerror = function (e) {
                console.log(e);
                log('操作失败: ' + e.target.error);
                error && error();
            };
        }

        function log(msg) {
            $('#record').append(`<p>${msg}</p>`);
        }

        function clearLog() {
            $('#record').empty();
        }

        // operation
        function insert() {
            let id = $('#id').val();
            let name = $('#name').val();
            let age = $('#age').val();
            let email = $('#email').val();
            add({ id, name, age, email });
        }

        function add(person) {
            transaction(getObjectStore('person').add({ name: person.name, age: person.age, email: person.email }), () => {
                log('插入成功');
                queryAll();
            });
        }

        function deleteById() {
            let id = $('#delId').val();
            // 删除错误id不会报错
            transaction(getObjectStore('person').delete(+id), (e) => {
                if (e.target.result) {
                    log('删除成功');
                    queryAll();
                } else {
                    log(`id为${id}的记录不存在`);
                }
            });
        }

        function update() {
            let id = +$('#updateId').val();
            let name = $('#updateName').val();
            let age = $('#updateAge').val();
            let email = $('#updateEmail').val();
            // 修改错误id不会报错,且会新增记录
            transaction(getObjectStore('person').put({ id, name, age, email }), () => {
                log('修改成功');
                queryAll();
            });
        }

        function queryById() {
            let id = $('#queryId').val();
            // 查询错误id不会报错,result为undefined
            transaction(getObjectStore('person').get(id), (e) => {
                let v = e.target.result || {};
                log(`查询id为${id}结果: <p>${v.id || '--'} | ${v.name || '--'} | ${v.age || '--'} | ${v.email || '--'}</p>`);
            });
        }

        function queryByIndex() {
            let content = $('#index').val();
            let index = $('input[name=index]:checked').val();
            // 查询错误index会报错;但是对于存在的index,错误的搜索内容不会报错,result为undefined
            transaction(getObjectStore('person').index(index).get(content), (e) => {
                let v = e.target.result || {};
                log(`查询${index}为${content}结果: <p>${v.id || '--'} | ${v.name || '--'} | ${v.age || '--'} | ${v.email || '--'}</p>`);
            });
        }

        function clearTable() {
            transaction(getObjectStore('person').clear(), (e) => {
                log('清空成功');
            });
        }

        function queryAll() {
            let request = getObjectStore('person').getAll();
            transaction(request, (e) => {
                let res = e.target.result;
                let content = `<p>查询结果:id | name | age | email</p>`;
                res.forEach((v) => {
                    content += `<p>${v.id || '--'}(${typeof v.id}) | ${v.name || '--'} | ${v.age || '--'} | ${v.email || '--'}</p>`;
                });
                $('#all').html(content);
            });
        }

        function test() {
            transaction(getObjectStore('person').getAllKeys(), (e) => {
                console.log(e);
            });
        }
    </script>
</body>

相关文章

  • webDB简介与使用

    简介及应用场景 浏览器的大数据量存储方式,相当于数据库,webSql为关系型DB,indexDB为非关系型DB。 ...

  • Groovy简介与使用

    简介使用应用 Groovy语法特性(相比于Java) Groovy与Java项目集成使用GroovyShellGr...

  • FindBugs:简介与使用

    目前已转至个人博客,本系列地址:Lam's Blog - Knowledge as Action 前言 FindB...

  • CMake 简介与使用

    2017.07.05 本文希望用短平快的方式,解决Cmake软件的安装配置使用问题,更进一步的参数配置与工程测试、...

  • Markdown简介与使用

    简介: Markdown是一种轻量级的标记语言,它能让我们使用易读易写的纯文本格式编写文档,然后转换成有效的HTM...

  • Systemd简介与使用

    按下电源键,随着风扇转动的声音,显示器上开启的图标亮起。之后,只需要静静等待几秒钟,登录界面显示,输入密码,即可愉...

  • Lombok简介与使用

    最近项目中有人用到了Lombok,一些注解搞得我头晕晕的,借着学习来简单的给大家总结一下。 官网介绍 搜索Lomb...

  • Lucene简介与使用

    1. Lucene简介与安装: 1.1 简介:1.2 索引与搜索流程:1.3 基本概念:2. 安装与使用:2.1...

  • 使用ONNX部署深度学习和传统机器学习模型

    目录 ONNX简介 ONNX标准介绍 ONNX与PMML DaaS简介 使用ONNX部署传统机器学习模型 使用ON...

  • linux-Ubuntu

    linux简介 linux命令行的使用 Ubuntu系统的安装与使用

网友评论

      本文标题:webDB简介与使用

      本文链接:https://www.haomeiwen.com/subject/tkggjrtx.html