// indexDB 存储 import { post } from '@af-mobile-client-vue3/services/restTools' // 避免重复请求相同配置key的锁 const locks: any = {} export const indexedDB = { db: undefined, indexedDB: window.indexedDB, IDBKeyRange: window.IDBKeyRange, // 键范围 openDB(callback: Function) { // 建立或打开数据库,建立对象存储空间(ObjectStore) if (this.db) { callback(this.db) } else { const version = 1 const request = this.indexedDB.open('view', version) request.onerror = function (e: any) { console.error(`打开数据库失败:${e.currentTarget.error.message}`) } request.onsuccess = function (e: any) { this.db = e.target.result callback(this.db) } request.onupgradeneeded = function (e: any) { const db = e.target.result if (!db.objectStoreNames.contains('metaCache')) { // 没有该对象空间时创建该对象空间 db.createObjectStore('metaCache', { keyPath: 'key', }) } } } }, deleteDB(dbname: string) { // 删除数据库 this.indexedDB.deleteDatabase(dbname) }, closeDB() { if (!this.db) this.db.close() }, add(key: string, data: any) { // eslint-disable-next-line ts/no-this-alias const self = this self.openDB((res: IDBDatabase) => { const request = res.transaction('metaCache', 'readwrite').objectStore('metaCache').add({ key, data, }) request.onerror = function () { self.update(key, data) } request.onsuccess = function () { } }) }, update(key: string, data: any) { this.openDB((res: IDBDatabase) => { const request = res.transaction('metaCache', 'readwrite').objectStore('metaCache').put({ key, data, }) request.onerror = function () { console.error('数据更新失败') } request.onsuccess = function () { } }) }, get(key: string, callback: Function) { this.openDB((res: IDBDatabase) => { // 根据存储空间的键找到对应数据 const store = res.transaction('metaCache', 'readwrite').objectStore('metaCache') const request = store.get(key) request.onerror = function () { } request.onsuccess = function (e: any) { const result = e.target.result if (typeof (callback) === 'function') callback(result.data) } }) }, getByWeb(key: string, url: string, params: any, callback: Function, processFun: Function) { // 如果这个键正在被使用,等待它完成 if (locks[key]) { locks[key].then(() => { this.getByWeb(key, url, params, callback, processFun) }) return } // 创建一个新的 Promise locks[key] = new Promise((resolve, reject) => { // eslint-disable-next-line ts/no-this-alias const self = this self.openDB((res: IDBDatabase) => { // 根据存储空间的键找到对应数据 const store = res.transaction('metaCache', 'readwrite').objectStore('metaCache') const request = store.get(key) request.onerror = function (e) { reject(e) } request.onsuccess = function (e: any) { const result = e.target.result if (!result && url) { post(url, params).then((res) => { if (processFun) res = processFun(res) if (import.meta.env.NODE_ENV === 'production' || key !== 'webMobileConfig') self.add(key, res) try { callback(res) } catch (e) { console.error(e) } // 解锁这个键 resolve() }).catch(() => { if (import.meta.env.NODE_ENV === 'production' || key !== 'webMobileConfig') self.add(key, null) callback(null) // 解锁这个键 resolve() }) } else { callback(result.data) // 解锁这个键 resolve() } } }) }).finally(() => { // 移除这个键的锁 delete locks[key] }) }, delete(key: string) { this.openDB((res: IDBDatabase) => { // 删除某一条记录 const request = res.transaction('metaCache', 'readwrite').objectStore('metaCache').delete(key) request.onerror = function () { console.error('数据删除失败') } request.onsuccess = function () { } }) }, clear(callback?: Function) { this.openDB((res: IDBDatabase) => { // 删除存储空间全部记录 const request = res.transaction('metaCache', 'readwrite').objectStore('metaCache').clear() request.onerror = function () { console.error('数据删除失败') } request.onsuccess = function () { if (typeof callback === 'function') callback() } }) }, clearDB() { return new Promise((resolve, reject) => { this.openDB((res: IDBDatabase) => { // 删除存储空间全部记录 const request = res.transaction('metaCache', 'readwrite').objectStore('metaCache').clear() request.onerror = () => { reject(new Error('数据删除失败')) } request.onsuccess = () => { resolve() } }) }) }, clearCache() { indexedDB.clear(() => { location.reload() }) }, }