应用场景
indexedDB 可以用在哪里呢?我想用于前端的数据缓存。
因为项目里面需要用到很多meta(json文件),放在 indexedDB 可以持久使用,不需要总是到服务端下载。
加载json的几种方式
在vite里面,可以多种方式加载json文件,比如import 、axios 等。各有利弊我们来分析一下。
import
使用 import 的方式加载 json 文件很方便,但是会处理成 js 的形式加载。
这个倒是无所谓,只是我还想实现热更新的功能。
也就是打包发布之后,可以直接修改json文件,而不需要重新打包。
但是经过import处理之后,找不到json跑到哪里去了。
另外打包发布之后,可能需要增加新的json文件,这样就无法通过import 的方式加载了。
所以import的方式无法满足我的需求。
axios
一般用 axios 访问后端API,当然也可以访问json文件。
试了一下加载json文件,发现这个状态有点“飘”。


第一次访问,返回200,需要从服务端加载文件,好几十毫秒。
第二次访问,返回304,使用了缓存,但是还是需要十多毫秒的处理时间,虽然合并 json 文件,应该能够够快一点,但是并不能解决根本问题。
另外多试几次就会发现,返回200还是304,并不是很固定,似乎比较随意的感觉,我不喜欢这种不可控的感觉。
另外,为啥大小不一样?
设计一个缓存方案
缓存,看着似乎挺简单的,但是实际上还是很难的,不过不怕,我们可以一点一点来,先设计一个简单的缓存。
我们可以先用axios把需要的json加载进来,然后存入 indexedDB,等到需要使用的时候,再从indexedDB里面读取出来。
我们可以设计一段代码:
// 访问 indexedDB
import { installIndexedDB } from '../../packages/indexedDB.js'
// axios
import axios from 'axios'
// json文件的列表
import { metaList } from '/jsonPlat/loadModule.json'
// 引入数据库数据
const db = {
dbName: 'nf-meta-catch',
ver: 1
}
let url = '/public/json-plat/'
/**
* 打开数据库,建立表,对表建立实例。
*/
export default installIndexedDB.createHelp({
dbConfig: db,
stores: { // 数据库里的表
moduleMeta: { // 模块的meta {按钮,列表,分页,查询,表单若干}
id: 'moduleId',
index: {},
isClear: false
}
},
init (help) {
const model = {
moduleId: {
buttonId: 142,
grid: {},
button: {},
find: {},
forms: {}
}
}
const actionName = [ 'button', 'find', 'grid' ]
const loadModuleMeta = []
console.log('整理url(import)', window.performance.now())
for (const key in metaList) {
const meta = metaList[key] // 模块需要的表单
// 添加按钮、列表、查询
actionName.forEach(action => {
const _url = `${url}${key}/${action}.json`
loadModuleMeta.push(axios.get(_url))
})
// 添加url
meta.forEach(form => {
const _url = `${url}${key}/${form}.json`
loadModuleMeta.push(axios.get(_url))
})
}
// 加载
console.log('axios 开始加载json:', window.performance.now())
Promise.all(loadModuleMeta).then((res) => {
console.log('axios 加载json完毕:', window.performance.now())
if (res[0].status === 200) {
const modulesMeta = {}
// 分类meta
res.forEach(re => {
const model = re.data
if (typeof modulesMeta[model.moduleId] === 'undefined') {
modulesMeta[model.moduleId] = {
moduleId: model.moduleId
}
}
if (typeof model.btnOrder === 'object') {
// 按钮
modulesMeta[model.moduleId].button = model
} else if (typeof model.quickFind === 'object') {
// 查询
modulesMeta[model.moduleId].find = model
} else if (typeof model.idName === 'string') {
// 列表
modulesMeta[model.moduleId].grid = model
} else if (typeof model.formId !== 'undefined') {
// 表单
if (typeof modulesMeta[model.moduleId].forms === 'undefined') {
modulesMeta[model.moduleId].forms = {}
}
modulesMeta[model.moduleId].forms[model.formId] = model
}
})
help.beginInit('moduleMeta').then((store) => {
// 添加到indexedDB
console.log('indexedDB开始添加数据:', window.performance.now())
for (const key in modulesMeta) {
const meta = modulesMeta[key]
store.add(meta) // 添加对象
.onsuccess = (event) => { // 成功后的回调
console.log('插件 —— 添加完毕:', window.performance.now())
}
}
})
}
})
}
})
加载计时
先看看执行时间,如果太慢的话,就尴尬了。

第一次访问,需要先加载json文件,用时 600多毫秒。
整理之后把meta加入 indexedDB里面,大概0.5毫秒左右可以添加一条,有时候快点有时候慢点,总体来看还是比较快的。
最后七十多毫秒后才会提交事务。


加入indexedDB 的meta
这是处理之后加入indexedDB 的 meta。

读取使用
填入meta只是实现了一半的功能,然后还需要读取出来给组件设置属性。
console.log('列表组件获得help:', window.performance.now())
getModel(help, 'moduleMeta', { id: props.moduleId }).then((res) => {
console.log('列表组件获得meta:', window.performance.now())
moduleMeta.button = res.button
moduleMeta.grid = res.grid
moduleMeta.find = res.find
moduleMeta.forms = res.forms
Object.assign(girdMeta, res.grid)
})
来看看读取数据的效果

好尴尬,居然用了200多毫秒。这个好慢呀。
分解动作
还是查一下慢在哪里吧。

在几个节点上加了计时,结果发现开启事务居然花了一、二百毫秒。
开表挺快,但是提取数据居然花了70多毫秒。还是挺无语的。
话说,为啥读比写还要慢?
网友评论