typedoc地址:https://jianli.pnote.net/db/docs

1. 背景

随着业务功能不断增强,需要有大量数据储存在客户端,这样可以减少从服务器获取数据的时间并缓解服务器压力。

现有的浏览器数据储存方案,都不适合储存大量数据:Cookie 的大小不超过4KB,LocalStorage 在 2.5MB 到 10MB 之间(各家浏览器不同),而且不提供搜索功能,不能建立自定义的索引。所以,需要一种新的解决方案来满足业务需求,IndexedDB 不仅可以储存字符串,还可以储存二进制数据。

2. 目标

  • 使用类似 localStorage API, 无需考虑 IndexedDB 的复杂概念
  • 提供更大的存储空间,具体的上限按照磁盘剩余空间进行计算,一般来说不少于磁盘空间的50%
  • 提供异步存储操作,以防止数据操作量大时,阻塞其他进行的操作
  • 每个database可以有多个table,可以根据业务需求存储到不同的表

3. 设计思路

封装为类似localStorage API的使用方式,并提供数据库和表的操作

根据IndexedDB的结构来对其操作进行分类:

  • 数据库操作
  • 数据表操作
  • 数据操作

4. 方案设计

4.1 整体结构

jg

4.2 方案设计图

WX20210621-175821@2x

4.3 设计大纲

  • 数据操作

    可通过db、store指定对应的库和表

    • set(key: IDBValidKey, value: any, storeName?: string, dbName?: string)

      ​ 把键值对添加到存储中,如果键名存在,则更新其对应的值

    • get(key: IDBValidKey, storeName?: string, dbName?: string)
      接受一个键名作为参数,返回键名对应的值

    • remove(key: IDBValidKey, storeName?: string, dbName?: string)
      接受一个键名作为参数,并把该键名从存储中删除

    • clear(storeName?: string, dbName?: string)
      清空存储中的所有数据
      清空某库下面的表存储数据

    • count(storeName?: string, dbName?: string)
      获取数据数量

  • 对象操作

    • deleteStore(storeName: string, dbName?)
      删除指定对象
      删除某库下面的对象
  • 数据库操作

    • closeDB(dbName: string)
      关闭数据库
    • deleteDB(dbName: string)
      删除数据库

4.4 部分示例

import db from "@iwww/indexedDB";
// or
import { db } from "@iwww/indexedDB";

/**
 * 库名表名是可选参数,不传则使用默认库名和表名
 * 默认库名: db_name
 * 默认表名: store_name
 */
(async () => {
    /**
     * 设置缓存,返回key (传入新的表名会新建表)
     * @param {IDBValidKey} key
     * @param value
     * @param {number | undefined} expired  过期时间,以小时为单位,不传或传0代表永不过期
     * @param {string | undefined} storeName
     * @param {string | undefined} dbName
     */
    await db.set('key', 'value')
    await db.set('key1', 'value1', {
        expired: 2,
        storeName: 'table1'
    })
    await db.set('key2', 'value2', {
        storeName: 'table2',
        dbName: 'dbName'
    })

    //  获取缓存
    await db.get('key').then(console.log).catch(console.log)
    await db.get('key', 'tableName')
    await db.get('key', 'tableName', 'dbName')

    //  清除缓存
    await db.remove('key')
    await db.remove('key', 'tableName')
    await db.remove('key', 'tableName', 'dbName')

    //  清理所有缓存或某库某表的缓存
    await db.clear()
    await db.clear('tableName')
    await db.clear('tableName', 'dbName')

    //  删除数据库
    await db.deleteDB()
    await db.deleteDB('db_name')
})();

4.5 目录结构

├── dist
│   ├── index.d.ts	# 声明文件
│   ├── indexedDB.d.ts
│   └── index.umd.js	# 在package.json - main指定lib入口
├── example	# 使用示例
│   ├── index.html
│   └── index.ts
├── src	# 实现
│   ├── index.ts
│   └── indexedDB.ts
├── webpack	# 构建配置
│   ├── build.config.js
│   └── dev.config.js
├── .gitignore
├── .prettierignore
├── README.md
├── package.json
├── tsconfig.json
└── vite.config.ts