什么是indexDB
- 一个 事务型 数据库系统 【注】
- 一个基于 JavaScript 的面向对象数据库
- 支持索引,可快速查找数据
- 可以存储 结构化克隆算法 支持的任何对象
不能被结构化克隆算法复制的数据
结构化克隆算法 用于复制复杂 JavaScript 对象的算法,它通过递归输入对象来构建克隆,同时保持先前访问过的引用的映射,以避免无限遍历循环。
- Error 以及 Function 对象
- DOM 节点
- 属性描述符,setters 以及 getters
- 原形链上的属性
结构化克隆算法支持的类型
-
JavaScript 类型
-
Error 类型
仅支持以下 Error 类型:Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError(或其他会被设置为 Error)
indexedDB特点
-
以键值对方式存储,键可以是二进制对象。
-
支持事务,这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
-
支持异步操作,不是基于Promise的异步,而是基于回调函数的异步。
-
遵循同源策略,每一个数据库对应创建它的域名,网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
-
存储空间配额很大,一般来说不少于 250MB,甚至没有上限。
indexedDB主要对象模型
基本操作流程
- 打开数据库
- 在数据库中创建/对开一个对象仓库
- 启动一个事务,并发送一个请求来执行一些数据库操作,像增加或提取数据等
- 通过监听事件以等待操作完成
- 继续后续的操作
代码示例: 以上代码建议大家复制出来,在本地运行进行调试,效果会更好喔👀
实用场景
- 缓存数据,比如游戏数据
- 缓存图片,脚本,json文件等等静态资源
- service worker的第三方库,就有利用到indexedDB
indexedDB第三方库
1、localForage
-
localForage 是一个 JavaScript 库,通过简单类似 localStorageAPI 的异步存储来改进你的Web 应用程序的离线体验。它能存储多种类型的数据,而不仅仅是字符串。
-
ocalForage 有一个优雅降级策略,若浏览器不支持 IndexedDB 或 WebSQL,则使用 localStorage。
-
localForage 提供回调 API 同时也支持 ES6 Promises API ,你可以自行选择。
<script src="./localforage.min.js"></script>
<script>
localforage.config({
// 指定存储媒介, localStorage, web sql, localStorage
driver: localforage.INDEXEDDB,
// 数据库名
name: "myApp",
// 版本
version: 1.0,
// 配额
size: 4980736,
// 对象库名
storeName: "keyvaluepairs",
description: "some description",
});
// 实例1
var store = localforage.createInstance({
name: "nameHere",
});
// 实例2
var store2 = localforage.createInstance({
name: "otherName",
});
(async function () {
// 实例1存和取
await store.setItem("key-1", "value-1", console.log);
const storeValue1 = await store.getItem("key-1");
console.log("store key-1:", storeValue1);
// 实例2存和取
await store2.setItem("key-1", "value-1", console.log);
const store2Value1 = await store.getItem("key-1");
console.log("store2 key-1:", storeValue1);
// 纯二进制
store.setItem("key-2", new Blob(["sdsd"]));
})();
</script>
GitHub 地址:github.com/localForage…
中文教程:localforage.docschina.org/
2、dexie.js
解決了原生 indexdb API 的三个主要问题:
- 不明确的错误处理
- 糟糕的查询
- 代码复杂性
<script type="module">
import Dexie from "./dexie.min.mjs";
// 实例化
const db = new Dexie("FriendDatabase");
db.version(1).stores({
friends: "++id,name,age",
});
try {
// 添加
await db.friends.add({ name: "Josephine", age: 21 });
// 查询
const youngFriends = await db.friends.where("age").below(25).toArray();
console.log(`My young friends: ${JSON.stringify(youngFriends)}`);
} catch (e) {
console.log(`Error: ${e}`);
}
</script>
3、ZangoDBs
一个类似于 MongoDB 的IndexedDB接口实现,提供了诸如过滤、投影、排序、更新和聚合等大多数MongoDB 常见的特性。
<script src="./zangodb.min.js"></script>
<script>
let db = new zango.Db('mydb', { people: ['age'] });
let people = db.collection('people');
let docs = [
{ name: 'Frank', age: 20 },
{ name: 'Thomas', age: 33 },
{ name: 'Todd', age: 33 },
{ name: 'John', age: 28 },
{ name: 'Peter', age: 33 },
{ name: 'George', age: 28 }
];
people.insert(docs).then(() => {
return people.find({
name: { $ne: 'John' },
age: { $gt: 20 }
}).group({
_id: { age: '$age' },
count: { $sum: 1 }
}).project({
_id: 0,
age: '$_id.age'
}).sort({
age: -1
}).forEach(doc => console.log('doc:', doc));
}).catch(error => console.error(error));
</script>
GitHub 地址:github.com/erikolson18…
4、JsStore
一个具备类 SQL 语法的简单和先进的 IndexedDB 封装实现
<script src="./jsstore.min.js"></script>
<script src="./jsstore.worker.js"></script>
<script>
// 定义数据结构
function getDbSchema() {
var table = {
name: "Student",
columns: {
id: {
primaryKey: true,
autoIncrement: true,
},
name: {
notNull: true,
dataType: "string",
},
gender: {
dataType: "number",
default: "male",
},
country: {
notNull: true,
dataType: "string",
},
city: {
dataType: "string",
notNull: true,
},
},
};
var db = {
name: "My-Db",
tables: [table],
};
return db;
}
// 实例化
var jsstoreCon = new JsStore.Connection();
async function initDb() {
// 创建数据库
var isDbCreated = await jsstoreCon.initDb(getDbSchema());
if (isDbCreated) {
console.log("db created");
} else {
console.log("db opened");
}
// 添加
await addStudent();
// 查询
var students = await jsstoreCon.select({
from: "Student",
});
console.log("students", students);
}
async function addStudent() {
try {
var noOfDataInserted = await jsstoreCon.insert({
into: "Student",
values: [
{
name: "小名",
gender: 1,
country: "北京",
city: "北京",
},
{
name: "小红",
gender: 0,
country: "新疆",
city: "乌鲁木齐",
},
],
});
} catch (ex) {
console.log("addStudent error:", ex.message);
}
}
initDb();
</script>