快速上手indexedDb进行业务开发

3,024 阅读5分钟

这篇文章不是对indexedDb进行详细介绍,只是我在上手使用中发现完整介绍怎么使用indexedDB的资料实在太少,大部分就是为了混个阅读量简单介绍一下,所以整理一些我在使用过程中的经验方便大家在业务压力下快速上手

传送门

developer.mozilla.org/zh-CN/docs/…

dexie.org/docs/

在你使用IndexedDB之前你需要先弄懂的 1 什么是IndexedDB 2 为什么要用IndexedDB 然后再看怎样用,当然你急着要用可以直接跳过

官方解释 IndexedDB是一个基于JavaScript的面向对象的数据库。 IndexedDB允许您存储和检索用键索引的对象;可以存储结构化克隆算法支持的任何对象。

首先他是个数据库,那么作为数据库你就要明白他的基本模式就是一个库(db)里边装若干个表(table),然后再看他的一些特色

1 他是基于键值对存储的这一点和storage有点像

2 支持结构化数据的存储

3 由于indexedDb是存储在本地磁盘,所以理论上硬盘有多大就可以存多少

4 他的所有操作都是异步

indexedDB is an asynchronous database, meaning that any operation that requires a result won’t be returned directly

5 支持事务

Whenever you are going to do more than a single operation on your database in a sequence, you would normally use a transaction. Transaction represents a full ACID transaction

ACID 原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)

再根据他的特性和业务考量为什么要不要使用indexedDb,如果就是想存存用户信息,token之类的还是用JSON+storage吧,即插即用同步操作,安全又方便。但是如果是需要缓存大量的结构化数据文件,就像我的业务每个用户都有4到5份大小为10M+的对应的文件需要从服务器下载过来,如果每次都去请求接口重复的去下载文件,会造成极大的资源损失,这时候我只需要以用户的唯一标识作为key将对应的数据在第一次请求时缓存起来就可以了

OK,现在再来看如果简单快捷的使用 由于indexedDb的原生api用起来有些繁琐,所以我选择的别人封装的特别好的一个三方库dexie.js,我这边是基于Vue生态也就是ES modules环境

1 npm install dexie --save

2 新建配置文件dbConfig.js(名字随意)

import Dexie from 'dexie';

const db = new Dexie('db');
db.version(1).stores({
    pd: `flagStr`,
});
db.version(2).stores({
    doc: '&examUID'
});

export default db;

api

1 建立数据库 var db = new Dexie(databaseName, options?);

Dexie is the main class and the default export of the library. An instance of this class represents an indexedDB database connection.

这里传入数据库的名字和后边的配置项即可生成Dexie实例作为数据库的连接,以后的所有增删改查都是基于这个实例,我们没有特殊处理的情况下传个数据库名就可以了

2建完库然后就是建表语句了 version.stores(schemaDefinition);

Object where each key represents the name of an object store and each value represents the primary and secondary indexes

schemaDefinition 是建表规则,传入一个对象以key为表名,val作为表的字段名和相关规则 注意indexedDb和mysql是有区别的,他不用像sql建表一样把所有的字段名都写出来,你只需要声明你需要的主键之前我就踩过这个坑

Unlike SQL, you don’t need to specify all properties but only the one you wish to index.

错误示例
// db.version(2).stores({
//     doc: '&examUID,reportStatus,relateReport,FontReport,ExamResult,ExamImage,ExamFilm,LabRequest'
// });

然后把数据库对象抛出即可

3 在main.js内全局引用挂载在vue对象上即可全局使用

import db from '../src/config/dbConfig'
Vue.prototype.db = db

4 最后根据实际业务对数据库进行增删改成即可,由于indexedDb是异步的。你可以使用回调,promise,async都随意,这里可以参考我对异步的处理 我使用的async,在对数据库的操作封装成一个个async方法,由于async方法返回的是一个promise对象,同样可以await来同步他

generateFcn.js
  // 缓存内取出报告数据
  async getCacheDoc(uid, docType) {
    let d = await db.doc.get({ examUID: uid });
    if (!d) return false
    if(!d[docType]) return false
    return d[docType]
  }
....


XXXPage.vue
...
import fcn form '@generateFcn.js'
method:{
    async getDoc(){
        let r = await this.fcn.getCacheDoc(....)
        console.log(r)
    }
}
...
  
 

最后在介绍几个常用的api,由于我所涉及的业务场景对indexedDB只有存储和获取的需求,所以也只介绍相关api,大家如有需要可以直接上文档查询,都是些顾名思义的api

1 tabke.clear()

顾名思义,和storage的clear()一样用于清空数据库

2 table.count()

返回当前版本库内数据的条数

3 table.put(主键,data) 我主要用来对做新增操作,如果当前版本库没有该主键的数据则新增,如果有则覆盖

If an object with the same primary key already exists, it will be replaced with the given object. If it does not exist, it will be added.

4 table.update(主键,data) 这个我主要用来做某条数据的更新操作,比如更新某个用户的某个报告,这个时候你用put就会把原来的替换掉了,当数据库没有这条数据的时候是没用的,所以我一般是先查有没有再决定用哪个

5 table.get(主键)

顾名思义

5 如果定时清除缓存

由于业务比较赶,所以我这边直接setInterval了,由于setInterval的回调时宏任务,primise的回调时微任务,所以每次清空之前,所有的数据库操作都会执行完,感谢js的单线程事件循环我们不用担心清空和数据库操作同时发生而产生的问题

 setInterval(()=>{
     db.doc.count(x=>{
         if(x!==0) db.doc.clear()
     })
 },10000)