美文网首页Vue.js前端开发那些事儿每天学一点Vue3
封装 indexedDB(二)分析一下执行顺序

封装 indexedDB(二)分析一下执行顺序

作者: 自然框架 | 来源:发表于2021-08-02 18:42 被阅读0次

    这次先不封装增删改查了,而是先看看执行顺序到底是什么样子的。

    我们给 help 里面加上一些标记:

    import { isRef, isReactive, toRaw } from 'vue'
    
    export default class IndexedDBHelp {
      constructor (info) {
        this.myIndexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB
        // 记录连接数据库的对象
        this._db = null
        // 打开数据库
        this.dbRequest = this.myIndexedDB.open(info.dbName, info.ver)
        console.log('【0】开启数据库 ')
        // 打开成功,记录连接对象
        this.dbRequest.onsuccess = (event) => {
          this._db = event.target.result // dbRequest.result
          console.log('【1】成功打开数据库 onsuccess --- ', this._db)
        }
        // 根据配置信息建立表
        this.dbRequest.onupgradeneeded = (event) => {
          const db = event.target.result
          console.log('【2】升级数据库 onupgradeneeded --- ', db)
          // 建表
          const object = {
            objectStoreName: 'aa'
          }
          // 验证有没有,没有的话建立一个对象表
          if (!db.objectStoreNames.contains(object.objectStoreName)) {
            const objectStore = db.createObjectStore(object.objectStoreName, { autoIncrement: true }) 
          }
        }
      }
    
      // 读写的事务
      beginWrite (storeName) {
        return new Promise((resolve, reject) => {
          const _tran = () => {
            const tranRequest = this._db.transaction(storeName, 'readwrite')
            tranRequest.onerror = (event) => {
              console.log('读写事务出错:', event.target.error)
              reject('读写事务出错:' + event.target.error)
            }
            resolve(tranRequest)
          }
    
          if (this._db) {
            console.log('【11】内部开启事务,获得对象 ')
            _tran() // 执行事务
          } else {
            console.log('【10】内部没有获得对象,使用计时器 ')
            let i = 0
            const val = setInterval(() => {
              console.log(`【11】 内部计时器: ${i++} --- `, this.dbRequest.readyState)
              // 检查 _db 和状态
              if (this._db && this.dbRequest.readyState === 'done') {
                console.log(`【12】 取消计时器: ${i++} --- `, this._db)
                console.log(`【13】 取消计时器: ${i} --- `, this.dbRequest.readyState)
                clearInterval(val) // 取消
                _tran() // 执行事务
              }
            }, 2)
          }
        })
      }
     
    

    使用代码

    
    const info = {
      dbName: 'test',
      ver: 1
    }
    const help = new IndexedDB(info)
    
    console.log('help', help)
    console.log('【3】外部 读取 开启状态 readyState', help.dbRequest.readyState)
    
    const model = {
      id: new Date().valueOf(),
      name: 'jyk666',
      age: 19
    }
    help.beginWrite(['aa']).then((tran) => {
      addModel(help, 'aa', model, tran)
    })
    

    然后看看执行情况。

    没有建立数据库的情况

    第一次执行,肯定没有数据库,这时候会触发 onupgradeneeded ,那么问题来了,它和 onsuccess 谁先回调?还有这期间 dbRequest.readyState 都是啥状态?

    我们来运行看看:

    没有数据库的情况

    过程:想要打开数据库 =》 触发建表(onupgradeneeded)=》成功打开数据库(onsuccess)
    同时:计时器等待中。。。

    最后:执行添加操作。

    执行结果

    事实证明,dbRequest.readyState 并不靠谱,onupgradeneeded 之后就变成了 none了,但是此时还在建表中,并没有执行 onsuccess 。所以还是需要判断 _db。

    有数据库的情况

    有了数据库 , onupgradeneeded 就不会被执行(ver不变的情况下),那么来看看执行情况:

    已经有数据库

    这次就简单多了,计时器等待一轮,就拿到了连接对象。

    升级数据库的情况

    如果版本号升级,又会如何?还是来看看执行情况:

    升级数据库

    版本号升级,又触发了 onupgradeneeded ,流程和没有数据的差不多。

    修改版本号,然后保存文件,这时 vite 会自动更新,但是会触发计时器的死循环。这时需要刷新一下页面。具体原因不详。

    相关文章

      网友评论

        本文标题:封装 indexedDB(二)分析一下执行顺序

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