IndexedDB的二次封裝

前言

瀏覽器數(shù)據(jù)庫(kù)存儲(chǔ)indexDB(非關(guān)系型數(shù)據(jù)庫(kù)),考慮到同步的場(chǎng)景,針對(duì)其固有api進(jìn)行二次封裝以滿(mǎn)足需求。

初始化數(shù)據(jù)庫(kù)

考慮到每次使用api都要基于db進(jìn)行操作,且需要判斷是否進(jìn)行過(guò)數(shù)據(jù)庫(kù)的開(kāi)啟,定義公用方法openDB來(lái)獲取db并進(jìn)行存儲(chǔ)。

openDB() {
  return new Promise((resolve, reject) => {
    // 判斷是否已經(jīng)打開(kāi)數(shù)據(jù)庫(kù)
    if (this.db) {
      resolve(this.db)
    } else {
      const request = window.indexedDB.open('庫(kù)的名字')
      // 首次創(chuàng)建數(shù)據(jù)庫(kù)
      request.onupgradeneeded = (event) => {
        const db = event.target.result
        // to do something...
      }
      request.onsuccess = () => {
        this.db = request.result
        resolve(request.result)
      }
      request.onerror = (error) => { reject(error) }
    }
  })
}
創(chuàng)建表

當(dāng)創(chuàng)建完數(shù)據(jù)庫(kù)后,對(duì)所需的表進(jìn)行創(chuàng)建;
可以創(chuàng)建對(duì)象不得缺少指定屬性的表{ keyPath: 'id' },或者是使用自動(dòng)遞增的整數(shù)作為鍵名的表{ autoIncrement: true }。

// ... ... 
// 首次創(chuàng)建數(shù)據(jù)庫(kù)
request.onupgradeneeded = (event) => {
  const db = event.target.result
  // to do something...
  db.createObjectStore('表名', { keyPath: 'id' })
  db.createObjectStore('表名', { autoIncrement: true })
}
// ... ... 

如果需要建立索引(可以根據(jù)索引快速查找數(shù)據(jù))。

let store = db.createObjectStore('表名', { keyPath: 'id' })
orglistStore.createIndex('索引', '索引', { unique: false })
插入數(shù)據(jù)

創(chuàng)建完表后,封裝插入數(shù)據(jù)方法setItem。

/**
 * @param {String} name 表名
 * @param {Object} obj 數(shù)據(jù)項(xiàng)
 * @param {Any} key 對(duì)應(yīng)的位置
 */
async setItem(name, obj, key = 'object') {
  const db = await this.openDB()
  // 將key值合并至對(duì)象
  let newObj = obj
  if (key) {
    newObj = Object.assign(obj, { key })
  }
  return new Promise((resolve, reject) => {
    const request = db.transaction([name], 'readwrite')
      .objectStore(name)
      .put(newObj)
    request.onsuccess = (event) => {
      resolve(request.result)
    }
    request.onerror = (error) => {
      reject(error)
    }
  })
}
讀取數(shù)據(jù)

1.單項(xiàng)數(shù)據(jù)獲取getItem,返回的值為對(duì)象。

/**
 * @param {String} name 表名
 * @param {Number} key 
 */
async getItem(name, key = 'object') {
  const db = await this.openDB()
  return new Promise((resolve, reject) => {
    const request = db.transaction([name], 'readwrite')
      .objectStore(name)
      .get(key)
    request.onsuccess = (event) => {
      resolve(request.result)
    }
    request.onerror = (error) => {
      reject(error)
    }
  })
}

2.根據(jù)索引獲取數(shù)據(jù)
由于可能有匹配多個(gè)索引的數(shù)據(jù),所以這里進(jìn)行循環(huán)查詢(xún),返回的值為數(shù)組。

/**
 * @param {String} name 表名
 * @param {String} index 索引名
 * @param {Any} val 索引值
 */
async getItemByIndex(name, index, val) {
  const db = await this.openDB()
  return new Promise((resolve, reject) => {
    let arr = []
    const request = db.transaction([name], 'readwrite')
      .objectStore(name)
      .index(index)
      .openCursor(val)
    request.onsuccess = (event) => {
      let cursor = event.target.result
      if (cursor) {
        let obj = cursor.value
        obj.key = cursor.primaryKey
        arr.push(obj)
        cursor.continue()
      } else {
        resolve(arr)
      }
    }
    request.onerror = (error) => {
      reject(error)
    }
  })
}

3.獲取表所有數(shù)據(jù)getAll,同索引循環(huán)表進(jìn)行查詢(xún),返回的值為數(shù)組。

/*
 * @param {String} name 表名
 */
async getAll(name) {
  const db = await this.openDB()
  return new Promise((resolve, reject) => {
    let arr = []
    const request = db.transaction([name], 'readwrite')
      .objectStore(name)
      .openCursor()
    request.onsuccess = function (event) {
      let cursor = event.target.result
      if (cursor) {
        arr.push({ ...cursor.value, key: cursor.key })
        cursor.continue()
      } else {
        resolve(arr)
      }
    }
    request.onerror = (error) => {
      reject(error)
    }
  })
}
數(shù)據(jù)清理

1.單項(xiàng)數(shù)據(jù)清除removeItem。

/*
 * @param {String} name 表名
 * @param {Any} key 
 */
async removeItem(name, key = 'object') {
  const db = await this.openDB()
  return new Promise((resolve, reject) => {
    const request = db.transaction([name], 'readwrite')
      .objectStore(name)
      .delete(key)
    request.onsuccess = function (event) {
      resolve()
    }
    request.onerror = (error) => {
      reject(error)
    }
  })
}

2.清理表clear。

/*
 * @param {String} name 表名
 */
async clear(name) {
  const db = await this.openDB()
  return new Promise((resolve, reject) => {
    const request = db.transaction([name], 'readwrite')
      .objectStore(name)
      .clear()
    request.onsuccess = function (event) {
      resolve()
    }
    request.onerror = (error) => {
      reject(error)
    }
  })
}
尾語(yǔ)

定義類(lèi)IndexDB,設(shè)置以上方法,導(dǎo)出實(shí)例后的對(duì)象。

class IndexDB {
  constructor () {
    this.db = null // 初始化數(shù)據(jù)庫(kù)
  }

  // 定義方法...
}

export default new IndexDB()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容