乐趣区

关于php:PHPGo-开发仿简书实战高并发高可用微服务架构王盘分xiang

网潘货区:PHP+Go 开发仿简书,实战高并发高可用微服务架构王盘分 xiang

<p>JavaScript IndexedDB 齐全指南
本文将通过一个小型的 crmeb 教程向您介绍 IndexedDB,并将 IndexedDB 与其余可用选项进行比拟。IndexedDB 用于在浏览器中存储数据,尤其实用于须要脱机工作的 web 应用程序(比方大多数高级 web 应用程序)。

首先,让咱们介绍一下为什么咱们须要在 web 浏览器中存储数据。数据在 web 应用程序中无处不在——用户通过交互来创立数据、查找数据、更新数据和删除数据。如果没有方法存储这些数据,就不可能容许用户交互在多个 web 应用程序的应用中放弃状态。你通常应用 MySQL、Postgres、MongoDB、Secondary、ArangoDB 等数据库来解决这些存储,然而如果你想让利用离线工作呢?

这在开发 web 应用程序时尤其重要,web 应用程序复制了原生应用程序的感觉,但位于浏览器中。这些渐进式 web 应用程序必须离线工作,因而它们须要一个存储选项。侥幸的是,有几个对于如何在浏览器中存储数据的工具,能够在线和离线拜访数据。

1. 浏览器存储模式
至于如何在浏览器中存储数据,Web 规范提供了三个次要的 API:

Cookies: 这些数据存储在浏览器中。Cookies 的大小限度为 4k。通常当服务器响应一个申请时,它们可能蕴含一个 SET-COOKIE 头,让浏览器存储一个键和值。而后,客户机应该在未来的申请头中蕴含这个 cookie,这将容许服务器辨认浏览器会话等。这些 cookie 通常具备 HTTP-Only 属性,这意味着不能通过客户端脚本拜访 cookie。这使得 cookie 不是保留离线数据的好抉择。
本地存储 / 会话存储: 本地存储 / 会话存储是浏览器内置的键值存储,其中每个键的大小限度为 5MB。LocalStorage 存储数据,直到它被删除,而 sessionStorage 将在浏览器敞开时主动革除。否则,它们的 API 是雷同的。能够应用 window . local storage . setitem(” key “,” value “)增加键值对。并应用 window . local storage . getitem(” key “)检索一个值。留神,LocalStorage API 是同步的,所以应用它会阻塞浏览器中的其余流动,这可能是一个问题。
IndexedDB: 内置于浏览器中的残缺文档数据库,没有存储限度。它容许您异步拜访数据,这对于避免简单操作阻塞演示和其余流动十分无效。这是咱们上面要深刻探讨的。
在这些办法中,localStorage 操作简略,存储数据量小,是一个不错的抉择。对于更简单或惯例的操作,IndexedDB 可能是更好的抉择,尤其是当您须要异步获取数据时。

IndexedDB API 比 LocalStorage API 更简单。因而,让咱们用 IndexedDB 构建一些货色,让您更好地理解它是如何工作的!

2. 用例
创立一个新的 HTML 文件,咱们称之为 index.html,内容如下:

索引数据库待办事项列表

注释 {
文本对齐: 居中;
}

h1 {
色彩: 棕色;
}

索引数据库待办事项列表

增加待办事项

// 保留输出变量
const textInput = document . query selector(“[type = ‘ text ‘]”)
const button = document . query selector(” button “)
// 保留 todos 的数组
const todos = []
// 出现 todos ‘ 函数
函数 renderTodos(){
const ul = document . query selector(” # todos ul “)
ul.innerHTML = ” “
对于(todos 的 todo){
ul.innerHTML += ${todo}
}
}
renderTodos()

复制代码

当初咱们能够开始设置 IndexedDB 了。在浏览器中关上此文件。如果应用的是 VS 代码,能够应用 liveserver 这样的扩大。

IndexedDB 反对很好,然而咱们还是想检查一下浏览器是否反对 API 的实现,这样你能够增加以下函数来查看。

// 查看 indexedDB 实现并返回其函数
函数 getIndexDB() {
常数索引 DB =
window.indexedDB ||
window.mozIndexedDB ||
window.webkitIndexedDB ||
window.msIndexedDB ||
window.shimIndexedDB
if (indexedDB){
返回索引 b
}
console.error(“ 此浏览器不反对 indexedDB “)
返回 null
}
复制代码

此函数返回 IndexedDB 的浏览器实现或浏览器不反对的日志。能够在浏览器中记录调用 getIndexDB 的后果,确认浏览器反对 IndexedDB。

您能够在上面看到兼容性列表。你能够在这里找到残缺的列表,包含挪动浏览器。
当初让咱们用 indexeddb.open (“database name “,1)关上一个数据库。open 的第一个参数是数据库的名称,第二个参数是数据库的版本。如果您心愿触发 onupgraderequired,您应该减少。公开通话。open 办法将返回一个具备多个属性的对象,包含 onerror、onupgradenneeded 和 onsuccess。每个属性都承受一个回调函数,该函数在相干事件产生时执行。

const indexedDB = getIndexDB()
// console.log(indexedDB)
const request = indexed db . open(” todo db “,1)
console.log(申请)
render todos();
复制代码

您应该会看到带有 IDBOpenDBRequest 对象的 console.log。IndexedDB 是基于事件的,这合乎它的异步模型。接下来,让咱们看一下数据库启动时可能产生的事件。首先,咱们将侦听 request.onerror 事件,以避免在拜访数据库时呈现任何谬误。

const indexedDB = getIndexDB()
// console.log(indexedDB)
const request = indexed db . open(” todo db “,1)
//console.log(申请)
//on 错误处理
request . on Error =(event)= > console . Error(” IndexDB Error:”,event)

render todos();
复制代码

咱们将监督的下一个事件是 request.onupgradeneeded 事件,当咱们尝试关上版本号高于数据库以后版本号的数据库时,该事件将运行。这是创立存储 / 表及其模式的性能。该性能在每个版本号下只执行一次。因而,如果您决定更改 onupgradedened 回调来更新您的模式或创立新的存储,那么版本号也应该在下一个。公开通话。存储实质上相当于传统数据库中的表。

const indexed db = getIndexDB();
// console.log(indexedDB)
const request = indexed db . open(” todo db “,1);
//console.log(申请)
//on 错误处理
request . on Error =(event)= > console . Error(” IndexDB Error:”,event);
//onupgradereneed
request . onupgradereneed =(){
// 获取数据库连贯
const db = request.result
// 定义新的存储
const store = db . createobjectstore(” todos ” ,{
keyPath: “id “,
主动增量: 真,
});
// 指定一个属性作为索引
store.createIndex(“todos_text “,[“text”],{unique: false})
};

render todos();
复制代码

在 onupgradeneeded 中,咱们做了以下工作:

获取数据库对象 (如果 onupgradenneeded 函数正在运行,您晓得它是可用的)
创立一个名为 todos 的新存储 / 表 / 汇合,它的键 id 是一个主动递增的数字 (记录的惟一标识符)
将 todos_text 指定为索引,这容许咱们稍后通过 todos_text 搜寻数据库。如果您不打算按特定属性进行搜寻,那么您不用创立索引。
最初,解决 request.onsuccess 事件,该事件在数据库连贯并存储所有设置和配置后运行。您能够利用这个机会提取 todo 列表,并将它们注入到咱们的数组中。

//onsuccess
request.onsuccess = () {
console.log(“ 数据库连贯已建设 ”)
// 获取数据库连贯
常量 db = request.result
// 创立一个事务对象
const tx = db.transaction(“todos “,” readwrite “)
// 创立一个存储在咱们这里的事务
const todos store = tx . objectstore(” todos “)
// 获取所有待办事项
const query = todosStore.getAll()
// 应用数据查问
query.onsuccess = () {
console.log(“ 所有待办事项: “,query.result)
for(query . result 的 todo
todos.push(todo.text)
}
renderTodos()
}
}
复制代码

咱们胜利地做到了以下几点:

获取数据库连贯
创立交易记录
指定咱们进行交易的存储。
运行 getAll 查问以获取存储中的所有文档 / 记录。
在查问特定的 onsuccess 事件时,咱们遍历 todos,将它们存储在 todos 数组中并调用 renderTodos(),因而它们被出现到 dom 中。
您应该在控制台中看到一个蕴含空数组的 console.log。

  • 谬误提醒: * 如果您运行的是热重装 web 服务器,如 liveserver,您可能会看到谬误“无存储”。这是因为 onupgradedneeded 函数是在您写完函数之前执行的。因而,对于该版本号,不会再次执行。解决办法是减少表的版本号,这将创立一个 onupgradereneed,onupgradereneed 回调将在下一次页面刷新时执行。

当初咱们曾经有了数据库设置,咱们能够依照雷同的模式来解决咱们心愿产生的任何其余事件。例如,让咱们在单击按钮时创立一个事件,该事件不仅会向 dom 增加一个新的 todo,还会向数据库增加一个新的 todo,以便在页面刷新时显示。

// 按钮事件
button.addEventListener(“click “,(event) => {
// 设置一个事务
常量 db = request.result
const tx = db.transaction(“todos “,” readwrite “)
const todos store = tx . objectstore(” todos “)
// 增加一个 todo
const text = textInput.value
Todos.push(text) // 将 todo 增加到数组中
TodosStore.put({text}) // 增加到 indexedDB
RenderTodos() // 更新 dom
})
复制代码

当初你能够增加 todos 了,因为你用的是 IndexedDB,无论你在线还是离线都能够。

增加一些 todo,当您刷新页面时,您会看到 todo 依然存在。它们还显示在查问后果的 console.log 中,并且每个 todo 都有一个惟一的 ID。到目前为止,残缺的代码应该是这样的:

索引数据库待办事项列表

注释 {
文本对齐: 居中;
}
h1 {
色彩: 棕色;
}

索引数据库待办事项列表

增加待办事项

// 保留输出变量
const textInput = document . query selector(“[type = ‘ text ‘]”);
const button = document . query selector(” button “);
// 保留 todos 的数组
const todos =[];
// 出现 todos ‘ 函数
函数 renderTodos() {
const ul = document . query selector(” # todos ul “);
ul.innerHTML =
对于 (todos 的 todo){
ul . innerhtml+= $ {todo}
}
}
// 查看 indexedDB 实现并返回其函数
函数 getIndexDB() {
常数索引 DB =
window.indexedDB ||
window.mozIndexedDB ||
window.webkitIndexedDB ||
window.msIndexedDB ||
window.shimIndexedDB
if (indexedDB) {
返回 indexedDB
}
console.log(“ 此浏览器不反对 indexed db “);
返回 null
}
const indexed db = getIndexDB();
// console.log(indexedDB)
const request = indexed db . open(” todo db “,2);
// console.log(申请)
//on 错误处理
request . on Error =(event)= > console . Error(” IndexDB Error:”,event);
//onupgradereneed
request . onupgradereneed =(){
// 获取数据库连贯
const db = request.result
// 定义新的存储
const store = db . createobjectstore(” todos ” ,{
keyPath: “id “,
主动增量: 真,
});
// 指定一个属性作为索引
store.createIndex(“todos_text “,[“text”],{unique: false})
};
// onsuccess
request.onsuccess = () {
console.log(“ 数据库连贯已建设 ”)
// 获取数据库连贯
常量 db = request.result
// 创立一个事务对象
const tx = db.transaction(“todos “,” readwrite “)
// 创立咱们的存储事务之一
const todos store = tx . objectstore(” todos “)
// 获取所有待办事项
const query = todosStore.getAll()
// 应用数据查问
query.onsuccess = () {
console.log(“ 所有待办事项: “,query.result)
for(query . result 的 todo
todos.push(todo.text)
}
renderTodos()
}
}
// 按钮事件
button.addEventListener(“click “,(event) => {
// 设置一个事务
常量 db = request.result
const tx = db.transaction(“todos “,” readwrite “)
const todos store = tx . objectstore(” todos “)
// 增加一个 todo
const text = textInput.value
Todos.push(text) // 将 todo 增加到数组中
TodosStore.put({text}) // 增加到 indexedDB
RenderTodos() // 更新 dom
})

render todos();

复制代码

todosStore 对象上可用于不同类型事务的其余办法:

革除: 删除商店中的所有记录。
增加: 插入具备给定 id 的记录 (如果它曾经存在,将会呈现谬误)
Put: 插入或更新具备给定 id 的记录(如果它曾经存在,它将被更新)
Get: 获取具备特定 id 的记录。
获取商店的所有记录。
Count: 返回存储中的记录数。
CreateIndex: 依据要查问的给定索引创立一个对象。
删除: 删除给定 id 的记录

3. 性能和其余思考因素
您须要思考以下几点:

并非所有浏览器都反对将文件存储为 blob。您会找到一个更好的办法: 将它们存储为 arraybuffer。
某些浏览器可能不反对在私人浏览模式下写入 IndexedDB。
IndexedDB 在写对象的时候会创立结构化克隆,这会阻塞主线程,所以如果你的大对象被更多的嵌套对象填充,这可能会造成一些提早。
如果用户敞开浏览器,任何未实现的事务都可能被停止。
如果另一个浏览器选项卡关上一个具备较新数据库版本号的应用程序,它将被阻止降级,直到所有旧版本选项卡被敞开 / 从新加载。侥幸的是,您能够应用 onblocked 事件来触发警报,告诉用户他们须要这样做。
只管 indexedDB 非常适合让您的应用程序脱机工作,但它不应该是您的次要数据存储。在互联网连贯中,您可能心愿将 indexedDB 与内部数据库同步,以便在用户革除浏览器数据时不会失落用户的信息。</p>

退出移动版