美文网首页前端开发那些事儿每天学一点Vue3
封装 indexedDB(四)应用场景(之一)

封装 indexedDB(四)应用场景(之一)

作者: 自然框架 | 来源:发表于2021-08-04 17:25 被阅读0次

应用场景

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 添加indexedDB的计时

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

网络监测 进度

加入indexedDB 的meta

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

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多毫秒。还是挺无语的。

话说,为啥读比写还要慢?

相关文章

  • 封装 indexedDB(四)应用场景(之一)

    应用场景 indexedDB 可以用在哪里呢?我想用于前端的数据缓存。因为项目里面需要用到很多meta(json文...

  • 3.保存绘制后的数据,重新进入显示在地图上

    内容需要用到之前封装的IndexedDB,用IndexedDB来保存数据。主要内容: 将绘制的图元保存。 页面加载...

  • indexedDB方法封装

    方法一 方法二 方法三 方法四 方法五 方法六 方法七 方法八 方法九 方法十 方法十一 可以通过es6的方法去全部导出

  • ES6 的 class

    最近又重构了 indexedDB 的封装,因为原来用的 class 的方式封装的,虽然实现了功能,但是感觉挺别扭的...

  • 防抖debounce

    应用场景,用户频繁操作,减少不必要的重复操作 封装的debounce

  • 封装 indexedDB(三)写个插件

    因为要在 vue 里面使用,所以做个插件可以方便很多。 项目需求 第一次访问,初始化,需要建立表、导入初始数据 组...

  • 封装 indexedDB(七)删除对象

    关系型数据库,一般会涉及到是物理删除,还是逻辑删除,而对象数据库,大概直接删掉就好了。 所以简单一点,直接删掉就好...

  • 工厂模式

    工厂模式:将 new 操作单独封装; 运用场景:遇到 new 时, 就要考虑是否要使用该模式; 应用场景示例 ...

  • 封装 indexedDB(一)做个help先

    不知道大家有没有发现,我封装了后端的 MySQL,前端的 webSQL,而现在又要对 indexedDB 下手了。...

  • runtime应用总结

    1.给category添加属性 应用场景:比如MJRefresh的封装,直接往tableview或者collect...

网友评论

    本文标题:封装 indexedDB(四)应用场景(之一)

    本文链接:https://www.haomeiwen.com/subject/ffujvltx.html