這篇文章不是對indexedDb進行詳細介紹,只是我在上手使用中發現完整介紹怎麼使用indexedDB的資料實在太少,大部分就是爲了混個閱讀量簡單介紹一下,所以整理一些我在使用過程中的經驗方便大家在業務壓力下快速上手
傳送門:
https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API
在你使用IndexedDB之前你需要先弄懂的 1 什麼是IndexedDB 2 爲什麼要用IndexedDB 然後再看怎樣用,當然你急着要用可以直接跳過
官方解釋 IndexedDB是一個基於JavaScript的面向對象的數據庫。 IndexedDB允許您存儲和檢索用鍵索引的對象;可以存儲結構化克隆算法支持的任何對象。
首先他是個數據庫,那麼作爲數據庫你就要明白他的基本模式就是一個庫(db)裏邊裝若干個表(table),然後再看他的一些特色
1 他是基於鍵值對存儲的這一點和storage有點像
2 支持結構化數據的存儲
3 由於indexedDb是存儲在本地磁盤,所以理論上硬盤有多大就可以存多少
4 他的所有操作都是異步
indexedDB is an asynchronous database, meaning that any operation that requires a result won’t be returned directly
5 支持事務
Whenever you are going to do more than a single operation on your database in a sequence, you would normally use a transaction. Transaction represents a full ACID transaction
ACID 原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)
再根據他的特性和業務考量爲什麼要不要使用indexedDb,如果就是想存存用戶信息,token之類的還是用JSON+storage吧,即插即用同步操作,安全又方便。但是如果是需要緩存大量的結構化數據文件,就像我的業務每個用戶都有4到5份大小爲10M+的對應的文件需要從服務器下載過來,如果每次都去請求接口重複的去下載文件,會造成極大的資源損失,這時候我只需要以用戶的唯一標識作爲key將對應的數據在第一次請求時緩存起來就可以了
OK,現在再來看如果簡單快捷的使用
由於indexedDb的原生api用起來有些繁瑣,所以我選擇的別人封裝的特別好的一個三方庫dexie.js,我這邊是基於Vue生態也就是ES modules環境
1 npm install dexie --save
2 新建配置文件dbConfig.js(名字隨意)
import Dexie from 'dexie';
const db = new Dexie('db');
db.version(1).stores({
pd: `flagStr`,
});
db.version(2).stores({
doc: '&examUID'
});
export default db;
api
1 建立數據庫 var db = new Dexie(databaseName, options?);
Dexie is the main class and the default export of the library. An instance of this class represents an indexedDB database connection.
這裏傳入數據庫的名字和後邊的配置項即可生成Dexie實例作爲數據庫的連接,以後的所有增刪改查都是基於這個實例,我們沒有特殊處理的情況下傳個數據庫名就可以了
2建完庫然後就是建表語句了
version.stores(schemaDefinition);
Object where each key represents the name of an object store and each value represents the primary and secondary indexes
schemaDefinition 是建表規則,傳入一個對象以key爲表名,val作爲表的字段名和相關規則
注意indexedDb和mysql是有區別的,他不用像sql建表一樣把所有的字段名都寫出來,你只需要聲明你需要的主鍵之前我就踩過這個坑
Unlike SQL, you don’t need to specify all properties but only the one you wish to index.
錯誤示例
// db.version(2).stores({
// doc: '&examUID,reportStatus,relateReport,FontReport,ExamResult,ExamImage,ExamFilm,LabRequest'
// });
然後把數據庫對象拋出即可
3 在main.js內全局引用掛載在vue對象上即可全局使用
import db from '../src/config/dbConfig'
Vue.prototype.db = db
4 最後根據實際業務對數據庫進行增刪改成即可,由於indexedDb是異步的。你可以使用回調,promise,async都隨意,這裏可以參考我對異步的處理
我使用的async,在對數據庫的操作封裝成一個個async方法,由於async方法返回的是一個promise對象,同樣可以await來同步他
例
generateFcn.js
// 緩存內取出報告數據
async getCacheDoc(uid, docType) {
let d = await db.doc.get({ examUID: uid });
if (!d) return false
if(!d[docType]) return false
return d[docType]
}
....
XXXPage.vue
...
import fcn form '@generateFcn.js'
method:{
async getDoc(){
let r = await this.fcn.getCacheDoc(....)
console.log(r)
}
}
...
最後在介紹幾個常用的api,由於我所涉及的業務場景對indexedDB只有存儲和獲取的需求,所以也只介紹相關api,大家如有需要可以直接上文檔查詢,都是些顧名思義的api
1 tabke.clear()
顧名思義,和storage的clear()一樣用於清空數據庫
2 table.count()
返回當前版本庫內數據的條數
3 table.put(主鍵,data)
我主要用來對做新增操作,如果當前版本庫沒有該主鍵的數據則新增,如果有則覆蓋
If an object with the same primary key already exists, it will be replaced with the given object. If it does not exist, it will be added.
4 table.update(主鍵,data)
這個我主要用來做某條數據的更新操作,比如更新某個用戶的某個報告,這個時候你用put就會把原來的替換掉了,當數據庫沒有這條數據的時候是沒用的,所以我一般是先查有沒有再決定用哪個
5 table.get(主鍵)
顧名思義
5 如果定時清除緩存
由於業務比較趕,所以我這邊直接setInterval了,由於setInterval的回調時宏任務,primise的回調時微任務,所以每次清空之前,所有的數據庫操作都會執行完,感謝js的單線程事件循環我們不用擔心清空和數據庫操作同時發生而產生的問題
setInterval(()=>{
db.doc.count(x=>{
if(x!==0) db.doc.clear()
})
},10000)