perf: 重做数据库框架

This commit is contained in:
blacktunes 2024-01-26 16:02:50 +08:00
parent 4fc5661b7a
commit 599a204053
4 changed files with 149 additions and 83 deletions

View File

@ -0,0 +1,129 @@
import { watch, nextTick, toRaw } from 'vue'
export class IndexedDB {
constructor(
public readonly name: string,
public readonly alias = ''
) {}
private DBList: Record<
string,
{
data: Record<string, any>
key: string
cb?: () => void
}
> = {}
private hasDB = true
db?: IDBDatabase
private index = 0
private doneList: Record<string, boolean> = {}
private doneCheck = (key: string) => {
this.doneList[key] = true
for (const i in this.DBList) {
if (!this.doneList[i]) return
}
this.cb?.()
}
private cb: ((value: void | PromiseLike<void>) => void) | undefined
private setWatch = (key: string) => {
this.doneCheck(key)
this.DBList[key]?.cb?.()
watch(this.DBList[key].data[this.DBList[key].key], () => {
nextTick(() => {
this.updateDB(key)
})
})
}
private updateDB = (key: string) => {
if (this.db) {
this.db
.transaction('data', 'readwrite')
.objectStore('data')
.put(JSON.parse(JSON.stringify(toRaw(this.DBList[key].data[this.DBList[key].key]))), key)
}
}
add = <T extends { [name: string]: any }, K extends keyof T & string>(data: {
data: T
key: K
name?: string
cb?: () => void
}) => {
let has = false
for (const i in this.DBList) {
if (this.DBList[i].data === data.data && this.DBList[i].key === data.key) {
has = true
break
}
}
if (has) return this
if (data.name) {
if (data.name in this.DBList) {
throw new Error('数据库key重复')
} else {
this.DBList[data.name] = {
data: data.data,
key: data.key,
cb: data.cb
}
}
} else {
this.DBList[this.index++] = {
data: data.data,
key: data.key,
cb: data.cb
}
}
return this
}
next = () => {
console.log(`正在加${this.alias}数据库...`)
return new Promise<void>((resolve, reject) => {
try {
const _db = window.indexedDB.open(this.name)
_db.onsuccess = (event) => {
this.db = (event.target as IDBOpenDBRequest).result
if (this.hasDB) {
for (const key in this.DBList) {
this.db.transaction('data', 'readonly').objectStore('data').get(key).onsuccess = (
res
) => {
try {
const data = (res.target as IDBRequest).result
if (data) {
this.DBList[key].data[this.DBList[key].key] = data
}
} finally {
this.setWatch(key)
}
}
}
} else {
for (const key in this.DBList) {
this.updateDB(key)
this.setWatch(key)
}
}
this.cb = () => resolve()
}
_db.onupgradeneeded = (event) => {
this.db = (event.target as IDBOpenDBRequest).result
if (!this.db.objectStoreNames.contains('data')) {
this.hasDB = false
this.db.createObjectStore('data')
}
}
} catch (err) {
reject(err)
} finally {
this.next = async () => {}
}
})
}
}

View File

@ -0,0 +1,19 @@
import { IndexedDB } from './indexedDB'
import { message } from '@/store/message'
import { character } from '@/store/character'
new IndexedDB('sr-ghostly-grove-v2', '罗浮杂俎')
.add({
data: message,
key: 'list',
name: 'mseeage'
})
.add({
data: character,
key: 'custom',
name: 'character'
})
.next()
.catch((err) => {
console.error(err)
})

View File

@ -1,7 +1,7 @@
import './main.styl'
import './assets/scripts/analytics'
import './store/indexedDB'
import './assets/scripts/setup'
import { createApp } from 'vue'
import App from './App.vue'

View File

@ -1,82 +0,0 @@
import { watch, nextTick, toRaw } from 'vue'
import { character } from './character'
import { message } from './message'
const setMessageWatch = () => {
watch(message.list, () => {
nextTick(() => {
updateDB(0, toRaw(message.list))
})
})
}
const setCustomWatch = () => {
watch(character.custom, () => {
nextTick(() => {
updateDB(1, toRaw(character.custom))
})
})
}
let hasDB = true
let db: IDBDatabase
interface updateDB {
(id: 0, data: Message[]): void
(id: 1, data: Character[]): void
}
export const updateDB: updateDB = (id, data) => {
db.transaction('data', 'readwrite')
.objectStore('data')
.put({
id,
data: JSON.parse(JSON.stringify(data))
})
}
export const getDB = () => {
console.log('正在加载罗浮杂俎数据库...')
const _db = window.indexedDB.open('sr-ghostly-grove')
_db.onsuccess = (event) => {
db = (event.target as IDBOpenDBRequest).result
if (hasDB) {
db.transaction('data', 'readonly').objectStore('data').get(0).onsuccess = (e) => {
try {
const data = (e.target as IDBRequest).result?.data
message.list = data || []
} finally {
setMessageWatch()
}
}
db.transaction('data', 'readonly').objectStore('data').get(1).onsuccess = (e) => {
try {
const data = (e.target as IDBRequest).result?.data
character.custom = data || []
} finally {
setCustomWatch()
}
}
} else {
updateDB(0, toRaw(message.list))
updateDB(1, toRaw(character.custom))
setCustomWatch()
setMessageWatch()
}
}
_db.onupgradeneeded = (event) => {
db = (event.target as IDBOpenDBRequest).result
if (!db.objectStoreNames.contains('data')) {
hasDB = false
db.createObjectStore('data', { keyPath: 'id' })
}
}
}
try {
getDB()
} catch (err) {
console.error(err)
}