浏览器缓存优化——indexDB
前言
开发大型项目,缓存数据非常大,localStorage最多也就5M的存储量,显然支撑不了。对于3D可视化项目,资源要达到几M甚至是几十M,如果全部放在服务器,每次加载都从服务器读取速度非常慢,能不能缓存在浏览器提升用户体验呢。
针对以上问题 indexDB 顺势而生,缓存容量无上限。
IndexDB介绍
打开控制台,既可看到IndexDB,它的存储方式更像树mysql的数据表,也有主键
如何操作IndexDB
话不多说直接上代码,这里代码是以封装的形式,大家可以放在本地使用,也可以根据需要打包成类库
类库代码
// 浏览器缓存 indexDB
/**
* dbName 数据库名
* storeName 表名
* indexList 索引列表
*/
/* 打开数据库 */
export function openDB(dbName, storeName, version = 1, indexList = []) {
return new Promise((resolve, reject) => {
let indexedDB = window.indexedDB
let db
const request = indexedDB.open(dbName, version)
request.onsuccess = function (event) {
db = event.target.result
resolve(db)
}
request.onerror = function (event) {
reject(event)
}
// 数据库创建或升级的时候会触发
request.onupgradeneeded = (e) => {
db = event.target.result
let objectStore
if (!db.objectStoreNames.contains(storeName)) {
objectStore = db.createObjectStore(storeName, { keyPath: 'id' })//设置主键
//添加自定义索引
if (indexList.length) {
indexList.forEach(item => {
objectStore.createIndex(item, item, { unique: false })//索引值可能会重复,所以设为false
})
}
}
}
})
}
/* 新增数据 */
export function addData(db, storeName, data) {
return new Promise((resolve, reject) => {
const request = db.transaction([storeName], 'readwrite')// 事务对象 指定表格名称和操作模式("只读"或"读写")
.objectStore(storeName)
.add(data)
request.onsuccess = (e) => {
resolve(e)
}
request.onerror = (e) => {
throw new Error(e.target.error)
}
})
}
/**
* 通过主键读取数据
*/
export function getDataByKey(db, storeName, key) {
return new Promise((resolve, reject) => {
const request = db.transaction([storeName])
.objectStore(storeName)
.get(key)
request.onsuccess = (e) => {
resolve(e.result)
}
request.onerror = (e) => {
throw new Error(e.target.error)
}
})
}
/* 通过游标读取数据 */
export function cursorGetData(db, storeName) {
let list = []
const request = db.transaction([storeName], 'readwrite')
.objectStore(storeName)
.openCursor()
return new Promise((resolve, reject) => {
request.onsuccess = (e) => {
let cursor = e.target.result
if (cursor) {
list.push(cursor.value)
cursor.continue() //遍历存储对象中所有内容
} else {
resolve(list)
}
}
request.onerror = (e) => {
reject(e)
}
})
}
/* 通过索引读取数据 */
export function getDataByIndex(db, storeName, indexName, indexValue) {
const request = db.transaction([storeName], 'readwrite')
.objectStore(storeName)
.index(indexName)
.get(indexValue)
return new Promise((resolve, reject) => {
request.onerror = function (e) {
reject(e)
}
request.onsuccess = function (e) {
resolve(e.target.result)
}
})
}
/**
* 通过索引和游标查询记录
*/
export function cursorGetDataByIndex(db, storeName, indexName, indexValue) {
let list = []
const request = db.transaction(storeName, 'readwrite').objectStore(storeName) // 仓库对象
.index(indexName) // 索引对象
.openCursor(IDBKeyRange.only(indexValue)) // 指针对象
return new Promise((resolve, reject) => {
request.onsuccess = function (e) {
let cursor = e.target.result
if (cursor) {
list.push(cursor.value)
cursor.continue() // 遍历了存储对象中的所有内容
} else {
resolve(list)
}
}
request.onerror = function (ev) {
reject(ev)
}
})
}
/* 更新数据 -- 没有则添加 */
export function updateDB(db, storeName, data) {
const request = db.transaction([storeName], 'readwrite')
.objectStore(storeName)
.put(data)
return new Promise((resolve, reject) => {
request.onsuccess = (ev) => {
resolve(ev)
}
request.onerror = (ev) => {
reject(ev)
}
})
}
/* 通过id 删除数据 */
export function deleteDB(db, storeName, id) {
const request = db.transaction([storeName], 'readwrite')
.objectStore(storeName)
.delete(id)
return new Promise((resolve, reject) => {
request.onsuccess = (ev) => {
resolve(ev)
}
request.onerror = (ev) => {
reject(ev)
}
})
}
/**
* 删除数据库
*/
export function deleteDBAll(dbName) {
let deleteRequest = window.indexedDB.deleteDatabase(dbName)
return new Promise((resolve, reject) => {
deleteRequest.onerror = function (event) {
reject('删除失败')
}
deleteRequest.onsuccess = function (event) {
resolve('删除成功')
}
})
}
/**
* 关闭数据库
*/
export function closeDB(db) {
db.close()
}
export default {
openDB,
addData,
getDataByKey,
cursorGetData,
getDataByIndex,
cursorGetDataByIndex,
updateDB,
deleteDB,
deleteDBAll,
closeDB
}