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设备的层次…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
QT开发技术【ffmpeg + QAudioOutput】音乐播放器
一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下,音视频内容犹如璀璨繁星,点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频,到在线课堂中知识渊博的专家授课,再到影视平台上扣人心弦的高清大片,音…...
