[javascript]前端快取資料的利器(idb)

[javascript]前端快取資料的利器(idb)

前言

最近遇到了一個要在前端操作快取資料的需求,以往總是為了方便直接記錄在sessionstorage或localstorage來實做,不過這次要操作的資料比較複雜,而且資料量過大存不進sessionstoreage裡面,已致於我不得不找其他的方案

開始研究了其他client端的存儲方案,而目前有另外兩種方式,一種是web sql,但已被多種瀏覽器給棄用,另一種就是目前主流的indexedDB了,而今天記錄的則是方便我們實做indexedDB的package,而且也已經幫我們包裝好了promise了,接下來就簡單記錄一下此工具吧。

關於indexedDB

indexedDB很類似於現在流行的no sql數據庫一樣,是使用key value的方式,我們可以建立Db and source最後就是此source要存放的資料,比如說我們有一個User的資料,key可能就會存放著這個User的編號,是絕對唯一值,另外一個value則是自行決定要怎麼放的概念。

為何不使用原生的,而選擇使用idb呢

其實一開始我是選擇自行實作原生的,但是有很多細節要自行處理,而且要好用的話還要思考自己得如何包裝,我們在操作indexedDb的api,幾乎全部都是非同步的,所以全部要自行去實做這方面和處理細節,時間要花在刀口上,有太多更重要的事情等著要去做,所以站在巨人的肩膀上幾乎都會是我的第一選項,所以選擇了已經完全幫我們包裝好Promise的indexedDB來實做。

開始實做吧

我們直接使用npm來下載

npm install idb

接著首先建立一個Db和object,這個object可視為一個資料表的概念

let dbPromise = idb.open('myDb', 1, upgradeDB => {
  upgradeDB.createObjectStore('employee')
})

此時我們從chrome的Application應該就可以看到相關的資訊都建立起來了


接著試著新增一些資料,而有一個關鍵字的readwrite的意思就是當我們需要針對資料異動的時候,必須得使用的,如果我們今天只是要讀取資料的話,最好的方式還是使用readonly的方式,因為如果只是讀取交易的話,可以多重同步進行哦,特別注意一下,put(你要存放的資料,key值),這點是比較特殊。

dbPromise.then(db => {
  const tx = db.transaction('employee', 'readwrite')
  let cacheData = [{ id: 1, name: 'dog' }, { id: 2, name: 'cat' }]
  tx.objectStore('employee').put(cacheData, 1)
  return tx.complete
})

而修改其實也是用同一種方式,我們只要key值對到了,我們就可以覆寫資料了

dbPromise.then(db => {
  const tx = db.transaction('employee', 'readwrite')
  let cacheData = [{ id: 1, name: 'cat' }, { id: 2, name: 'dog' }]
  tx.objectStore('employee').put(cacheData, 1)
  return tx.complete
})

接著就是刪除資料了,如下程式碼就可以囉,需特別注意,delete一定得要給key值

dbPromise.then(db => {
  const tx = db.transaction('employee', 'readwrite')
  tx.objectStore('employee').delete(1)
  return tx.complete
})

如果你想刪除全部資料的話,則得使用clear,只要下達clear的方法,就能把整個employee的資料全部刪除了,程式碼都大同小異

dbPromise.then(db => {
  const tx = db.transaction('employee', 'readwrite')
  tx.objectStore('employee').clear()
  return tx.complete
})

取得全部資料如下,這邊可以注意一下,我們在此並不需使用readwrite或readonly,預設就已經替我們指定好囉

dbPromise.then(db => {
  return db.transaction('employee').objectStore('employee').getAll()
}).then(x => console.log(x))

由id取得資料則如下

dbPromise.then(db => {
  return db.transaction('employee').objectStore('employee').get(1)
}).then(x => console.log(x))

取得所有的key值

dbPromise.then(db => {
  return db.transaction('employee').objectStore('employee').getAllKeys()
}).then(x => console.log(x))

查詢object裡面有多少筆資料

dbPromise.then(db => {
  return db.transaction('employee').objectStore('employee').count()
}).then(x => console.log(x))

甚至還有cursor和index的概念,有興趣或有需求的讀者可以查訪官網了解哦(https://github.com/jakearchibald/idb)