localStorage在JavaScript中是同步的。当你调用localStorage.setItem()或localStorage.getItem()时,操作会立即执行,并且会阻塞其他JavaScript代码的执行,直到操作完成。这意味着,如果你正在进行一个耗时的localStorage操作,可能会导致浏览器的用户界面暂时无响应。
存储位置
localStorage 是 Web Storage API 的一部分,它提供了一种存储键值对的机制。localStorage 的数据是持久存储在用户的硬盘上的,而不是内存。这意味着即使用户关闭浏览器或电脑,localStorage 中的数据也不会丢失,除非主动清除浏览器缓存或者使用代码删除。
当你通过 JavaScript 访问 localStorage 时,浏览器会从硬盘中读取数据或向硬盘写入数据。然而,在读写操作期间,数据可能会被暂时存放在内存中,以提高处理速度。但主要的特点是它的持久性,以及它不依赖于会话的持续性
硬盘是一个IO设备,大部分与硬盘相关的操作系统级IO操作确实是异步进行的,以避免阻塞进程,不过,在web浏览器环境中,localStorage的API是设计为同步的,即使底层的硬盘读写操作有着IO的特性。
js代码在访问localStorage时,浏览器提供的API接口通常会处于js执行线程上下文中直接调用,这意味着尽管硬盘是IO设备,当一个js执行流程访问localStorage时,他会同步等待数据读取或写入完成,该过程中js执行线程会阻塞。
执行流程
-
js线程调用: 执行localStorage getItem或者setItem操作,这个调用发生在js的单线程上;
-
浏览器引擎处理:浏览器的js引擎接收到调用请求后,会向浏览器的存储子系统发出同步IO请求,js引擎等待IO操作的完成
-
文件系统的同步IO: 浏览器存储子系统对硬盘执行实际的存储或检索操作。尽管操作系统层面可能对文件访问进行缓存或优化,但从浏览器的角度看,它会进行一个同步的文件系统操作,直到这个操作返回结果。
-
操作完成返回: 一旦IO操作完成,数据要么被写入硬盘,要么被从硬盘读取出来,浏览器存储子系统会将结果返回给 js 引擎。
-
JavaScript线程继续执行: js 引擎在接收到操作完成的信号后,才会继续执行下一条 js 代码。
localStorage限制容量是因为同步阻塞吗?
- 资源公平分享,防止单个网站消耗大量本地资源
- 防止滥用:存储大量数据在用户设备上,会导致设备资源空间迅速耗尽
- 性能限制:同步阻塞,影响页面性能
- 存储效率:存储数据大,会降低效率
- 历史和兼容性:5MB被大部分浏览器实现和采纳
- 浏览器政策
IndexedDB
IndexedDB 是一种在用户浏览器内持久化存储数据的方法。它可以让你创建具有丰富查询能力的 Web 应用,而无需考虑网络可用性,因此你的应用在在线和离线时都可以正常运行。
| 对比 | localStorage | IndexDB |
|---|---|---|
| 存储容量 | 5MB | 可以达到几百MB甚至更高,具体取决于用户的硬盘空间和浏览器的策略 |
| 数据类型 | 字符串,非字符串需转换成字符串 | 可以直接存储多种数据类型,包括对象、数组、字符串、日期等。 |
| 异步 vs 同步 | 同步 | 异步 |
| 查询能力 | 提供了非常基础的键值对存储,没有查询语言 | 提供了更复杂的查询能力,包括索引、游标和事务。 |
| 浏览器支持 | 现代浏览器兼容性好 | 部分浏览器不兼容 |
参考:juejin.cn/post/735940…
MDN: developer.mozilla.org/zh-CN/docs/…