IndexedDB & Dexie.js 使用经验

工作中遇到这样的一个场景:在实时编辑时,需要将产生的编辑操作上传到服务端(以 websocket 长连的方式),但当用户处于断线或弱网的情况下,我们需要将用户的所有操作存储在本地,等待网络恢复时再重传。

为什么选择 indexedDB 来进行本地存储?

  1. indexedDB 提供 key/value 的存储方式,不需要像 localStorage 那样转存为字符串。对于一次用户的编辑操作,往往对应着 文档ID、作者ID、操作内容 等字段,再次上传的时候需要筛选出该文档、该作者对应的操作内容,用这种存储方式显然更方便索引
  2. indexedDB 提供的存储空间很大,一篇离线文档所有操作数的大小往往是 MB 级别的。而 indexedDB 可提供超过 250MB 的存储空间,这也是 indexedDB 相较于 localStorage 最大的优势所在。

参考:前端大容量缓存方案-IndexedDB

如何使用 indexedDB?

我们选择了 Dexie.js 这个第三方库,它将 indexedDB 进行了封装,提供了简单而全面的 API。

1. 创建数据库

import Dexie from 'dexie'

// 创建名为 editor_database 的数据库
const db = new Dexie('editor_database')
// 这里可以定义版本号,后续修改表字段时可以增加版本号
db.version(1).stores({
  // 创建 docUpdate 表,&表示 primaryKey(++表示自增字段)
  docMessage: `&msgId,docId,userId,msgType,updates,status,createTime,updateTime`
})

export default db

2. 增删改查操作

import editorDB from './editorDB'

export default class DocMessage {
  constructor() {
    this.db = editorDB && editorDB.docMessage
  }

  // 添加一条消息记录
  async addMessage(msg) {
    const time = new Date().getTime()
    try {
      await this.db.add({
        ...msg,
        status: 0,
        createTime: time,
        updateTime: time
      })
    } catch (err) {
      console.error(err)
    }
  }

  // 删除单条消息记录
  async deleteMessageByMsgId(msgId) {
    try {
      await this.db.where({ msgId }).delete()
    } catch (err) {
      console.error(err)
    }
  }

  // 删除多条消息记录
  async deleteMessagesByMsgIds(msgIds) {
    try {
      await this.db
        .where('msgId')
        .anyOf(msgIds)
        .delete()
    } catch (err) {
      console.error(err)
    }
  }

  // 更新一条消息的状态
  async updateMessageStatus(msgId, status) {
    const time = new Date().getTime()
    try {
      await this.db
        .where('msgId')
        .equals(msgId)
        .modify({
          status,
          updateTime: time
        })
    } catch (err) {
      console.error(err)
    }
  }

  // 更新多条消息的状态
  async updateMessagesStatus(msgIds, status) {
    const time = new Date().getTime()
    try {
      await this.db
        .where('msgId')
        .anyOf(msgIds)
        .modify({
          status,
          updateTime: time
        })
    } catch (err) {
      console.error(err)
    }
  }

  // 查询某时间段内某文档的所有消息
  async filterMessagesByDocId(docId, startTime, endTime) {
    let messages = []
    try {
      messages = await this.db
        .where({ docId })
        .and((item) => item.createTime < endTime && item.createTime > startTime) // 也可以使用 above 和 below
        .toArray()
    } catch (err) {
      console.error(err)
    }
    return messages
  }

  // 查询某文档的所有消息
  async getAllMessagesByDocId(docId) {
    let messages = []
    try {
      messages = this.db.where({ docId }).sortBy('createTime')
    } catch (err) {
      console.error(err)
    }
    return messages
  }
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
IndexedDB是一种浏览器本地存储技术,可以用于存储大量的数据,包括二进制数据,因此可以用来存储three.js加载的模型文件。 在Vue中使用IndexedDB可以使用IndexedDB API进行操作,具体步骤如下: 1. 创建一个IndexedDB数据库 ```javascript let request = indexedDB.open('myDB', 1); request.onerror = function() { console.log('创建数据库失败'); }; request.onsuccess = function(event) { console.log('创建数据库成功'); }; request.onupgradeneeded = function(event) { let db = event.target.result; let objectStore = db.createObjectStore('models', { keyPath: 'id' }); }; ``` 这里创建了一个名为"myDB"的数据库,并创建了一个名为"models"的对象仓库,用于存储模型文件。 2. 将模型文件存储到IndexedDB中 ```javascript let db = request.result; let transaction = db.transaction(['models'], 'readwrite'); let objectStore = transaction.objectStore('models'); let fileReader = new FileReader(); fileReader.onload = function() { let model = { id: 'model1', data: fileReader.result }; let request = objectStore.add(model); request.onsuccess = function() { console.log('添加模型成功'); }; }; fileReader.readAsArrayBuffer(modelFile); ``` 这里使用FileReader将模型文件读取为ArrayBuffer类型,然后将其存储到IndexedDB中。 3. 从IndexedDB中获取模型文件 ```javascript let db = request.result; let transaction = db.transaction(['models'], 'readonly'); let objectStore = transaction.objectStore('models'); let request = objectStore.get('model1'); request.onsuccess = function(event) { let model = event.target.result; let arrayBuffer = model.data; // 使用arrayBuffer加载模型文件 }; ``` 这里从IndexedDB中获取id为"model1"的模型文件,并将其存储到arrayBuffer变量中,然后可以使用该arrayBuffer加载模型文件。 注意,IndexedDB在某些浏览器上并不支持,需要进行兼容性处理。另外,IndexedDB API使用起来相对复杂,需要注意事务管理等细节。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值