JavaScript 第19章:Web Storage
在JavaScript中,Web存储(Web Storage)提供了一种在用户浏览器中持久化数据的方式。这里我们会探讨localStorage、sessionStorage以及IndexedDB,并提供一些简单的示例代码来展示它们的用法。
localStorage
localStorage允许你在用户的浏览器中存储键值对数据,这些数据会一直保存,除非用户清除了浏览器的数据或开发者手动删除了这些数据。
示例代码:
// 存储数据
localStorage.setItem('name', 'John Doe');// 获取数据
let name = localStorage.getItem('name');
console.log(name); // 输出 "John Doe"// 删除数据
localStorage.removeItem('name');
sessionStorage
与localStorage类似,sessionStorage也是用来存储键值对数据,但是它仅在当前浏览器窗口或标签页的生命周期内有效。当用户关闭所有属于该站点的窗口或标签页时,这些数据会被清除。
示例代码:
// 存储数据
sessionStorage.setItem('sessionName', 'Jane Doe');// 获取数据
let sessionName = sessionStorage.getItem('sessionName');
console.log(sessionName); // 输出 "Jane Doe"// 删除数据
sessionStorage.removeItem('sessionName');
IndexedDB
IndexedDB是一个客户端数据库系统,允许存储大量的结构化数据,并且可以搜索索引。它适合存储比简单键值对更复杂的数据结构,如对象或二进制大对象(BLOBs)等。
示例代码:
let db;
const request = window.indexedDB.open('myDatabase', 1);request.onerror = function(event) {console.log('Error opening IndexedDB database.');
};request.onsuccess = function(event) {db = event.target.result;console.log('Database opened successfully.');
};request.onupgradeneeded = function(event) {let db = event.target.result;let objectStore = db.createObjectStore('users', {keyPath: 'id'});objectStore.createIndex('name', 'name', {unique: false});
};function addData() {let transaction = db.transaction(['users'], 'readwrite');let objectStore = transaction.objectStore('users');let newUser = {id: 1, name: 'Alice'};objectStore.add(newUser);
}function getData() {let transaction = db.transaction(['users'], 'readonly');let objectStore = transaction.objectStore('users');let request = objectStore.get(1);request.onsuccess = function(event) {let data = event.target.result;console.log(data);};
}
以上代码展示了如何创建一个名为myDatabase的数据库,并且包含了一个名为users的对象存储区(object store)。我们还定义了如何添加和检索数据的方法。注意,IndexedDB的操作通常是在异步事件处理程序中完成的。
这些例子只是基本的使用方法,实际应用中可能需要更复杂的错误处理逻辑以及事务管理。
IndexedDB 进阶示例
让我们扩展前面的例子,增加更多功能,比如更新数据、删除数据、遍历数据等。
更新数据
更新数据涉及到获取现有记录,修改它,然后将其放回存储中。
function updateData(id, updatedUser) {let transaction = db.transaction(['users'], 'readwrite');let objectStore = transaction.objectStore('users');objectStore.put(updatedUser);
}
在这个例子中,我们直接使用put方法来更新数据。如果提供的对象的键已经存在于对象存储中,则此操作将替换现有的条目。
删除数据
删除特定记录可以通过其主键来实现。
function deleteData(id) {let transaction = db.transaction(['users'], 'readwrite');let objectStore = transaction.objectStore('users');objectStore.delete(id);
}
遍历所有数据
要获取对象存储中的所有数据,我们可以使用游标(cursor)。
function getAllData() {let transaction = db.transaction(['users'], 'readonly');let objectStore = transaction.objectStore('users');let request = objectStore.openCursor();request.onsuccess = function(event) {let cursor = event.target.result;if (cursor) {console.log(cursor.key + ": " + JSON.stringify(cursor.value));cursor.continue();}};
}
这个函数会打印出对象存储中的每一项记录的键和值。
错误处理
在处理IndexedDB操作时,必须考虑错误处理。例如,在打开数据库时可能会失败,或者在事务执行过程中可能会遇到其他错误。
request.onerror = function(event) {console.error('An error occurred with the indexedDB request.');
};transaction.onerror = function(event) {console.error('An error occurred with the transaction.');
};
总结
IndexedDB是一个非常强大的API,它允许在客户端进行复杂的数据存储和检索。虽然它的API比localStorage和sessionStorage要复杂得多,但这也意味着它可以处理更加复杂的应用场景。为了有效地使用IndexedDB,你需要熟悉事务、游标、对象存储、索引等概念。
以上示例提供了一个基本框架来开始使用IndexedDB。在实际项目中,你可能还需要考虑更多高级特性,例如版本控制、事务回滚、并发控制等。
版本控制
当你的应用程序需要更改已存在的数据库结构时(例如添加新的对象存储、改变键路径、添加索引等),需要通过版本控制来管理这些更改。当打开数据库时,如果提供了新的版本号并且旧版本仍然存在,那么会触发onupgradeneeded事件。
request.onupgradeneeded = function(event) {let db = event.target.result;if (!db.objectStoreNames.contains('users')) {db.createObjectStore('users', { keyPath: 'id' });}let usersStore = db.transaction.objectStore('users');if (!usersStore.indexNames.contains('name')) {usersStore.createIndex('name', 'name', { unique: false });}
};
在这个例子中,我们检查是否存在users对象存储,并且检查是否存在name索引。如果不存在,则创建它们。
事务的回滚
在某些情况下,你可能希望在事务失败时回滚事务。这通常是通过设置事务的oncomplete和onerror事件处理器来实现的。
let transaction = db.transaction(['users'], 'readwrite');
transaction.oncomplete = function(event) {console.log('Transaction completed.');
};
transaction.onerror = function(event) {console.error('Transaction failed.');transaction.rollback();
};
在这个例子中,如果事务失败,将会记录错误信息并且回滚事务。
并发控制
IndexedDB支持多窗口或多标签页同时访问同一个数据库。为了防止数据冲突,IndexedDB使用锁定机制来确保在任何时刻只有一个事务可以修改一个给定的对象存储。
如果你的应用程序需要支持多个窗口之间的协调工作,你可能需要实现额外的逻辑来处理并发情况。例如,可以在事务开始前检查数据的状态,或者在事务提交后通知其他窗口数据已更改。
数据类型
IndexedDB支持多种数据类型,包括字符串、数字、日期、数组、对象等。然而,需要注意的是,某些类型的数据(如函数、undefined、Symbol等)不能直接存储在IndexedDB中。对于复杂对象,确保它们是可序列化的,并且在存储之前转换为JSON格式。
let user = {id: 1,name: 'John Doe',birthDate: new Date(),tags: ['developer', 'musician']
};objectStore.put(user);
性能优化
尽管IndexedDB非常强大,但在处理大量数据时,性能可能会成为一个问题。以下是一些提高性能的技巧:
- 使用索引:为频繁查询的属性创建索引。
- 批量操作:尽量使用事务来批量处理多个读写操作。
- 限制大小:避免存储过大的对象或过多的数据,这可能会导致内存和性能问题。
我们将继续探讨IndexedDB的一些实际应用和最佳实践,包括如何处理大数据量、如何进行数据迁移以及如何使用索引来提高查询效率。
处理大数据量
当IndexedDB用于存储大量数据时,性能和内存管理变得尤为重要。以下是一些处理大数据量的策略:
-
分批处理:当需要插入或更新大量数据时,可以将数据分成小批次进行处理。这样可以减少单个事务的负载,从而提高整体性能。
function batchAddUsers(users, batchSize) {let count = 0;let transaction = db.transaction(['users'], 'readwrite');let objectStore = transaction.objectStore('users');for (let user of users) {if (count % batchSize === 0) {transaction.oncomplete = function() {transaction = db.transaction(['users'], 'readwrite');objectStore = transaction.objectStore('users');};}objectStore.add(user);count++;} } -
垃圾回收:IndexedDB有一个内部的垃圾回收机制,可以自动清理不再使用的空间。但是,如果你知道某个对象存储不再需要,可以显式地删除它以释放空间。
db.deleteObjectStore('obsoleteStore');
数据迁移
当应用程序需要对数据库结构进行重大更改时,数据迁移就变得很重要。在onupgradeneeded事件中,你可以编写代码来处理数据迁移。
request.onupgradeneeded = function(event) {let db = event.target.result;if (event.oldVersion < 2) {db.createObjectStore('newUsers', { keyPath: 'id' });let transaction = db.transaction(['users'], 'readwrite');transaction.oncomplete = function() {db.close(); // 关闭旧数据库连接};let usersStore = transaction.objectStore('users');let newUsersStore = db.transaction('newUsers').objectStore('newUsers');usersStore.openCursor().onsuccess = function(event) {let cursor = event.target.result;if (cursor) {let newUser = Object.assign({}, cursor.value); // 复制旧用户数据newUsersStore.add(newUser);cursor.delete(); // 删除旧数据cursor.continue();}};}
};
在这个例子中,我们在新版本中创建一个新的对象存储,并从旧的存储中迁移数据。
使用索引提高查询效率
索引可以大大提高查询效率,尤其是在需要根据非主键字段进行查找的情况下。创建索引后,可以通过索引进行查询。
let objectStore = db.createObjectStore('users', { keyPath: 'id' });
objectStore.createIndex('name', 'name', { unique: false });// 查询名为 "Alice" 的用户
function findUserByName(name) {let index = db.transaction('users', 'readonly').objectStore('users').index('name');let request = index.get(name);request.onsuccess = function(event) {let user = event.target.result;console.log(user);};
}
安全性
在使用IndexedDB时,还需要考虑安全性。虽然IndexedDB本身是安全的,因为它只在客户端运行并且每个域名/协议组合都有自己的隔离存储空间,但你仍需小心处理敏感数据。
- 避免存储敏感信息:尽可能不要在IndexedDB中存储密码或其他敏感信息。
- 使用HTTPS:使用HTTPS来保护通信安全,防止中间人攻击。
结论
通过上述示例和建议,你应该能够更好地理解和使用IndexedDB来构建高性能的Web应用程序。如果你有特定的需求或问题,欢迎继续提问!
相关文章:
JavaScript 第19章:Web Storage
在JavaScript中,Web存储(Web Storage)提供了一种在用户浏览器中持久化数据的方式。这里我们会探讨localStorage、sessionStorage以及IndexedDB,并提供一些简单的示例代码来展示它们的用法。 localStorage localStorage允许你在用…...
[山河2024] week2
官方WP出得很快。对照官的写下私的。大概出入不大,毕竟第2周。后边的才难。 Crypto E&R RSA因子分解题,把q的2进制反转后与p异或。关于异或的题很多,这个还真是头一回见,不过爆破方法还是一样的。 r_q int(bin(q)[2:][::…...
无限可能LangChain——开启大模型世界
什么是大语言模型? 大语言模型是一种人工智能模型,通常使用深度学习技术(如神经网络)来理解和生成人类语言。这些模型拥有非常多的参数,可以达到数十亿甚至更多,使得它们能够处理高度复杂的语言模式。 我…...
URL路径以及Tomcat本身引入的jar包会导致的 SpringMVC项目 404问题、Tomcat调试日志的开启及总结
一、URL路径导致的 SpringMVC项目 404问题 SpringMVC项目的各项代码都没有问题,但是在页面请求时仍然显示404,编译的时候报了下面的问题: org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录…...
如何引起Java中的System.in.read()函数的异常
演示的为:关闭标准输入流System.in后再调用System.in.read就会报出IOException import java.io.IOException; import java.io.InputStream;public class Test {public static void main(String[] args) {InputStream in System.in;try {in.close();System.in.read();}catch (…...
深入理解Flutter鸿蒙next版本 中的Widget继承:使用extends获取数据与父类约束
目录 写在前面 什么是Widget继承? 基本概念 StatelessWidget与StatefulWidget build方法 创建自定义Widget 1. 继承StatelessWidget 2. 继承StatefulWidget并访问父类的约束 3. 继承其他自定义Widget并获取数据 写在最后 写在前面 在Flutter中,…...
Loss:Focal Loss for Dense Object Detection
目录 3. 焦点损失(Focal Loss)3.1. 平衡交叉熵3.2. 焦点损失定义3.3. 类别不平衡与模型初始化3.4. 类别不平衡与两阶段检测器4. RetinaNet 检测器。4.1. 推理与训练。3. 焦点损失(Focal Loss) 焦点损失(Focal Loss)旨在解决单阶段目标检测场景中训练时前景和背景类别之间…...
Unity3D中Excel表格的数据处理模块详解
前言 在Unity3D项目中,处理Excel表格数据是一项常见且重要的任务。通过Excel表格,我们可以方便地管理游戏配置、角色属性等数据内容。本文将详细介绍如何在Unity3D中实现Excel表格的数据处理模块,包括技术详解和代码实现。 对惹,…...
【python】OpenCV—Fun Mirrors
文章目录 1、准备工作2、原理介绍3、代码实现4、效果展示5、参考 1、准备工作 pip install vacm2、原理介绍 在OpenCV中,VCAM 库是一个用于简化创建三维曲面、定义虚拟摄像机、设置参数以及进行投影任务的工具。它特别适用于实现如哈哈镜等图像变形效果。 一、VC…...
QT IEEE754 16进制浮点数据转成10进制
IEEE754标准转换QT代码 qtcreator使用的ieee754标准的4字节数组与浮点数之间的转换方法,ieee754的4位数组如果转换成二进制后,大体结构是: 位序号12-910-32意义 符号位, 正数为0,负数为1. 指数位, 指数是…...
无人机+视频推流直播EasyCVR视频汇聚/EasyDSS平台在森林防护巡检中的解决方案
随着科技的飞速发展,无人机技术在各个领域的应用日益广泛,特别是在森林防护与巡检方面,无人机以其独特的优势,为传统林业管理带来了革命性的变化。本文将探讨无人机在森林防护巡检中的解决方案,分析其工作原理、优势及…...
Rancher—多集群Kubernetes管理平台
目录 一、Rancher 简介1.1 Rancher 和 k8s 的区别 二、Rancher 安装及配置2.1 安装 rancher2.2 登录 Rancher 平台2.3 Rancher 管理已存在的 k8s 集群2.4 创建名称空间 namespace2.5 创建 Deployment 资源2.6 创建 service2.7 Rancher 部署监控系统 一、Rancher 简介 Rancher …...
使用多IP香港站群服务器对网站管理seo优化提升排名有益处
在网站管理和优化中,选择合适的服务器是至关重要的。针对某些特定需求,使用多IP香港站群服务器可以带来明显的益处。本文将探讨使用多IP香港站群服务器 对网站管理的明显益处,并介绍其中的关键要点和优势。 I. 理解多IP香港站群服务器 1. 多I…...
网管平台(基础篇):网管系统的重要性
网管系统的核心地位:数字世界的稳定舵手 在信息技术日新月异的今天,网络如同一条无形的纽带,将世界紧密相连。然而,这条纽带背后隐藏着无数复杂的节点与链路,如何确保它们高效、稳定地运行,成为了一个亟待解…...
Ubuntu20.04下安装多CUDA版本,以及后续切换卸载
本方案的前提是假设机子上已经有一个版本的cuda,现在需要支持新的torch2.1.2和torchvision0.16.2,于是来安装新的cuda 一、选择版本 如果我想安装支持torch2.1.2的cuda版本,到官网(https://pytorch.org/get-started/previous-ve…...
图像处理高频面试题及答案
目录 高频面试题及答案1. 什么是图像处理?2. 什么是图像的分辨率?3. 图像的颜色空间是什么?4. 什么是边缘检测,为什么重要?5. 解释一下图像增强的常见方法。6. 什么是图像的直方图?7. 什么是图像的去噪声?8. 什么是图像分割,常用的方法有哪些?9. 图像滤波的目的是什么…...
尤雨溪都打赏的虚拟列表组件,到底有多强
尤雨溪都打赏的虚拟列表组件,到底有多强? 在前端开发中,性能优化永远是绕不开的主题。今天就带你看看 vue-virtual-scroller,一款让你滚动页面时流畅得像火箭一样的 Vue 组件。本文将简单介绍这个组件的主要功能、技术特点&#x…...
FrameWork使用EfCore数据库映射举例
Microsoft.EntityFrameworkCore新的版本不支持FrameWork框架。 这里举例使用旧版本实现数据存取 首先下载 Microsoft.EntityFrameworkCore 版本控制在2.1.14以下 同样下载Microsoft.EntityFrameworkCore.sqlite 举例时间记录 public class RunTimeInfo{[Key]public int Id { g…...
汽车与航空领域的功能安全对比:ISO 26262-6 与 DO-178C 的差异浅析
ISO 26262-6 和 DO-178C (航空系统与设备认证中的软件考量)。是汽车和航空领域分别广泛应用的软件安全标准。它们的共同目标是确保系统软件可靠性,减少系统软件故障对生命安全的威胁,但在具体的软件安全方案和规范实施上存在明显的…...
linux命令之lspci用法
lspci 显示当前主机的所有PCI总线信息 补充说明 lspci命令 用于显示当前主机的所有PCI总线信息,以及所有已连接的PCI设备信息。 语法 lspci(选项)选项 -n:以数字方式显示PCI厂商和设备代码; -t:以树状结构显示PCI设备的层次…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...
TJCTF 2025
还以为是天津的。这个比较容易,虽然绕了点弯,可还是把CP AK了,不过我会的别人也会,还是没啥名次。记录一下吧。 Crypto bacon-bits with open(flag.txt) as f: flag f.read().strip() with open(text.txt) as t: text t.read…...
