前端缓存——IndexDB封装

indexedDB是一种轻量级NOSQL数据库,是由浏览器自带。相比Web Sql更加高效,包括索引、事务处理和查询功能。
关于indexedDB的介绍请参考其他资料,本文主要基于ES6对indexedDB进行封装,废话不多说,直接上代码:

IndexedDB类

export type DBTable = {
     
  dbName: string;
  tables: string[];
  version?: number;
  callback?: any;
  storage?: any;
};

/**
 * Web缓存类,用于封装存储和获取对象值
 * @author huangsq
 */
export default class IndexedDB {
     
  dbName: string;

  tables: string[];

  version: number;

  callback?: any;

  storage: any;

  /**
   * 删除指定数据库
   * @param dbName 数据库名称
   */
  static deleteDB(dbName: string) {
     
    window.indexedDB?.deleteDatabase(dbName);
  }

  constructor(options: DBTable) {
     
    const {
      dbName, tables, version = 1, ...args } = options;
    this.dbName = dbName;
    this.tables = tables;
    this.version = version;
    this.openDB({
      dbName, tables, version, ...args });
  }

  /**
   * 根据主键删除指定表和主键中数据
   * @param table 表名
   * @param key 主键
   * @param callback 回调函数
   * @returns request
   */
  deleteItem(table: string, key: string, callback?: (args: any) => void) {
     
    const request = this.storage.transaction(table, 'readwrite').objectStore(table).delete(key);
    request.onsuccess = (event: any) => {
     
      if (typeof callback === 'function') {
     
        callback(event);
      }
    };
    return request;
  }

  /**
   * 获取当前数据库下指定表和主键对应的值,通过回调函数返回数据
   * @param table 表名
   * @param key 主键,key为null返回所有记录
   * @param callback 回调函数
   * @returns request
   */
  getItem(table: string, key: string | null, callback: any) {
     
    // 第二个参数可以省略
    const transaction = this.storage.transaction(table, 'readwrite');
    const store = transaction.objectStore(table);
    let request: any = null;
    if (key) {
     
      request = store.get(key);
    } else {
     
      request = store.getAll();
    }

    request.onsuccess = (event: {
      target: {
      result: any } }) => {
     
      if (typeof callback === 'function') {
     
        callback(event?.target?.result);
      }
    };
    request.onerror = (event: any) => {
     
      console.error(event);
      callback(event);
    };
    return request;
  }

  /**
   * 新增或更新数据到指定的表和主键中
   * @param table 表名
   * @param key 主键
   * @param value 值
   * @param callback 回调函数
   * @returns request
   */
  setItem(table: string, key: string, value: any, callback?: (args: any) => void) {
     
    const transaction = this.storage.transaction(table, 'readwrite');
    const store = transaction.objectStore(table);
    const request = store.put(value, key);
    request.onsuccess = (event: any) => {
     
      if (typeof callback === 'function') {
     
        callback(event);
      }
    };
    request.onerror = (event: any) => {
     
      if (typeof callback === 'function') {
     
        callback(event);
      }
    };
    return request;
  }

  /**
   * 获取第一个表中主键对应的值,通过回调函数返回数据
   * @param key 主键,key为null返回所有记录
   * @param callback 回调函数
   * @returns request
   */
  get(key: string | null, callback: any) {
     
    return this.getItem(this.tables[0], key, callback);
  }

  /**
   * 新增或更新数据到第一个表中主键对应的值
   * @param key 主键
   * @param value 值
   * @param callback 回调函数
   * @returns request
   */
  set(key: string, value: any, callback?: (args: any) => void | null) {
     
    return this.setItem(this.tables[0], key, value, callback);
  }

  /**
   * 根据主键删除指定表和主键中数据
   * @param table 表名
   * @param key 主键
   * @param callback 回调函数
   * @returns request
   */
  delete(key: string, callback?: (args: any) => void) {
     
    return this.deleteItem(this.tables[0], key, callback);
  }

  /**
   * 清空表数据
   */
  clear(table: string, callback?: (args: any) => void) {
     
    const request = this.storage.transaction(this.dbName, 'readwrite').objectStore(table).clear();
    request.onsuccess = (event: any) => {
     
      if (typeof callback === 'function') {
     
        callback(event);
      }
    };
    return request;
  }

  /**
   * 获取数据库对象
   */
  getDB(): any {
     
    return this.storage;
  }

  /**
   * 关闭数据库连接
   */
  closeDB() {
     
    this.storage.close();
  }

  /**
   * 打开数据库
   * @param options
   * @returns
   */
  openDB(options: DBTable) {
     
    const {
      dbName, tables, version, callback } = options;
    const {
      indexedDB } = window;
    if (!indexedDB) {
     
      console.error('你的浏览器不支持indexedDB');
      return;
    }
    if (tables?.length < 1) {
     
      console.error('表名不能为空');
      return;
    }
    const request = indexedDB.open(dbName, version);
    request.onerror = (event) => {
     
      console.error(`打开数据库失败: ${
       event.currentTarget?.error?.message}`);
      if (typeof callback === 'function') {
     
        callback(event);
      }
    };

    request.onsuccess = (event) => {
     
      this.storage = event.target?.result;
      if (typeof callback === 'function') {
     
        callback(event);
      }
    };

    request.onupgradeneeded = (event) => {
     
      this.storage = event.target?.result;
      tables.forEach((table) => {
     
        if (!this.storage.objectStoreNames.contains(table)) {
     
          this.storage.createObjectStore(table);
          // this.storage.createObjectStore(table, {
     
          //   keyPath: 'id',
          // });
          if (typeof callback === 'function') {
     
            callback(event);
          }
        }
      });
    };
  }
}

使用方式

注意: 使用时请使用单例模式,避免数据库多次打开没有关闭.

const db = new IndexedDB({
      dbName: 'yloo_cn', tables: ['ts_user', 'ts_role'] });
db.set('1', {
     userName: 'fa', userCode: 'fa'});
...

你可能感兴趣的:(前端,antd,vue,javascript,es6,typescript,reactjs,vue.js)