浏览器本地存储到现在已经发展到第 3 代,抛开事实上已经废弃的 web SQL,这个过程为:
cookie → web storage → indexed db
web storge 包含 localStorage 和 sessionStorage,其中 sessionStorage 在浏览器关闭后将不复存在。web storage 并不适合大文件的存储,这就带来了 indexedDB (索引数据库)。下面截取一段 MDN 上关于 IndexedDB 的用途说明:
IndexedDB is a low-level API for client-side storage of significant amounts of structured data, including files/blobs.
因此,IndexedDB 很适合缓存 文件/多媒体 这一类所需存储空间较大的数据。
浏览器实现方式
点击 caniuse 查看 IndexedDB 的浏览器支持情况。
就像使用其他类型的数据库一样,使用 indexedDB 的第一步也是去关联它:
const request = indexedDB.open('helloDB', 1) // @params: dbName, version
第二个参数表示数据库版本号,createObjectStore 只能在数据库版本号更改时才可以调用,即只能在onupgradeneeded
中创建 objectStore。
然后需要给 request 设置成功和失败的回调:
request.onsuccess = e => {
const db = e.target.result // db 是一个 IDBDatabase
}
request.onerror = err => {
console.error(err)
}
request.onupgradeneeded = e => { // IDBVersionChangeEvent
const db = e.target.result
}
版本更新时,onupgradeneeded 被调用,可在其中添加新的 objectStore:
const store = db.createObjectStore(storeName, {
keyPath: 'id', // 相当于主键
autoincrement: false
})
store.createIndex('index', 'filename', { unique: true })
createIndex 接收 3 个参数:索引名
、数据对象的属性
、配置对象
下面来做一个返回 Promise 的函数,它能在连接 indexedDB,并在 objectStore 不存在时创建它:
function openDB (dbName, version, storeName) {
return new Promise((resolve, reject) => {
const request = indexedDB.open(dbName, version)
request.onsuccess = function (e) {
resolve(e.target.result)
}
request.onerror = function (e) {
reject(e)
}
request.onupgradeneeded = function (e) {
const db = e.target.result
if (!db.objectStoreNames.contains(storeName)) {
const objectStore = db.createObjectStore(storeName, {
keyPath: 'id',
autoIncrement: true
})
objectStore.createIndex('index', 'filename', {
unique: false
})
}
}
})
}
这样,就可以在连接数据库后往 store 里放东西了:
function doSomethingToDb (dbName, version, storeName) {
openDB(dbName, version, storeName)
.then(db => {
const tx = db.transaction(storeName, 'readwrite')
const store = tx.objectStore(storeName)
const req = store.put({
filename: '涡轮增压机',
version: 102,
author: 'John'
})
req.onsuccess = res => {
console.log('保存成功', res)
}
})
.catch(err => {
console.error(err)
})
}
doSomethingToDb('worldDB', 1, 'Files')
const req = store.get('main_key')
req.onsuccess = (res) => {
console.log(res)
}
using-indexeddb-manage-3d-webgl-assets/
w3c IndexedDB(最权威的文档)
MDN: IndexedDB API