网易首页 > 网易号 > 正文 申请入驻

Web端IM聊天消息该不该用浏览器本地存储?一文即懂!

0
分享至

本文由转转技术团队刘筱雨分享,原题“一文读懂浏览器本地存储:Web Storage”,下文进行了排版和内容优化。

1、引言

鉴于目前浏览器技术的进步(主要是HTML5的普及),在Web网页端IM聊天应用的技术选型阶段,很多开发者都会纠结到底该不该像原生移动端IM那样将聊天记录缓存在浏览器的本地,还是像传统Web端即时通讯那样继续存储在服务端?本文将为你简洁明了地讲清楚浏览器本地存储技术(Web Storage),然后你就知道到底该怎么选择了。

浏览器本地存储是指浏览器提供的一种机制,允许 Web 应用程序在浏览器端存储数据,以便在用户下次访问时可以快速获取和使用这些数据。一共两种存储方式:localStorage 和 sessionStorage,本文将主要围绕这两种技术来进行总结。



2、初识浏览器本地存储(localStorage和sessionStorage)

2.1区别

localStorage 和 sessionStorage 的主要区别是生命周期。

具体区别如下:



容量限制的目的是防止滥用本地存储空间,导致用户浏览器变慢。

2.2浏览器兼容性

1)现在的浏览器基本上都是支持这两种 Storage 特性的。

各浏览器支持版本如下:



2)如果使用的是老式浏览器,比如Internet Explorer 6、7 或者其他,就需要在使用前检测浏览器是否支持本地存储或者是否被禁用。

以 localStorage 为例:

if(window.localStorage){
alert("浏览器支持 localStorage");
}else{
alert("浏览器不支持 localStorage");

3)某些浏览器版本使用过程中,会出现 Storage 不能正常使用的情况,记得添加try/catch。

以 localStorage 为例:

if(window.localStorage){
try{
localStorage.setItem("username","name");
alert("浏览器支持 localStorage");
}catch(e) {
alert("浏览器支持 localStorage 后不可使用");
}else{
alert("浏览器不支持 localStorage");

3、基本用法演示

3.1基本API

localStorage 和 sessionStorage 提供了相同的方法进行存储、检索和删除。

常用的方法如下:

1)设置数据:setItem(key, value)。存储的值可以是字符串、数字、布尔、数组和对象。对象和数组必须转换为 string 进行存储。JSON.parse() 和 JSON.stringify() 方法可以将数组、对象等值类型转换为字符串类型,从而存储到 Storage 中(示例代码如下)。

localStorage.setItem("username","name");// "name"
localStorage.setItem("count", 1);// "1"
localStorage.setItem("isOnline",true);// "true"
sessionStorage.setItem("username","name");
// user 存储时,先使用 JSON 序列化,否则保存的是[object Object]
const user = {"username":"name"};
localStorage.setItem("user", JSON.stringify(user));
sessionStorage.setItem("user", JSON.stringify(user));

eg:数据没有序列化,导致保存的数据异常:



2)获取数据:getItem(key)。如果 key 对应的 value 获取不到,则返回值是 null。

const usernameLocal = localStorage.getItem("username");
const usernameSession = sessionStorage.getItem("username");
// 获取到的数据为string,使用时反序列化数据
const userLocal = JSON.parse(localStorage.getItem("user"));
const userSession = JSON.parse(sessionStorage.getItem("user"));

3)删除数据:removeItem(key);

localStorage.removeItem("username");
sessionStorage.removeItem("username");

4)清空数据:clear();

localStorage.clear();
sessionStorage.clear();

5)在不确定是否存在 key 的情况下,可以使用 hasOwnProperty() 进行检查;

localStorage.hasOwnProperty("userName");// true
sessionStorage.hasOwnProperty("userName");// false

6)当然,也可以使用 Object.keys() 查看所有存储数据的键;

Object.keys(localStorage);// ['username']
Object.keys(sessionStorage);

3.2浏览器查看

本地存储的内容可以在浏览器中直接查看,以 Chrome 为例,按住键盘 F12 进入开发者工具后,选择 Application,然后就能在左边 Storage 列表中找到 localStorage 和 sessionStorgae。



3.3监听数据变化

当存储的数据发生变化时,其他页面通过监听 storage 事件,来获取变更前后的值,以及根据值的变化来处理页面的展示逻辑。

JS 原生监听事件,只能够监听同源非同一个页面中的 storage 事件,如果想监听同一个页面的,需要改写原生方法,抛出自定义事件来监听。

具体如下:

1)监听同源非同一个页面:

直接在其他页面添加监听事件即可。

eg:同域下的 A、B 两个页面,A 修改了 localStorage,B 页面可以监听到 storage 事件。

window.addEventListener("storage", () => {
// 监听 username 值变化
if(e.key ==="username") {
console.log("username 旧值:"+ e.oldValue +",新值:"+ e.newValue);

注:

  • 1)当两次 setItem 更新的值一样时,监听方法是不会触发的;
  • 2)storage 事件只能监听到 localStorage 的变化。

2)监听同一个页面:

重写 Storage 的 setItem 事件,同理,也可以监听删除事件 removeItem 和获取事件 getItem。


const originalSetItem = localStorage.setItem;
// 重写 setItem 函数
localStorage.setItem =function(key, val) {
letevent =newEvent("setItemEvent");
event.key = key;
event.newValue = val;
window.dispatchEvent(event);
originalSetItem.apply(this, arguments);

window.addEventListener("setItemEvent",function(e) {
// 监听 username 值变化
if(e.key ==="username") {
const oldValue = localStorage.getItem(e.key);
console.log("username 旧值:"+ oldValue +",新值:"+ e.newValue);

4、存储容量上限到底是不是5MB?

浏览器默认能够存储 5M 的数据,但实际上,浏览器并不会为其分配特定的存储空间,而是根据当前浏览器的空闲空间来判断能够分配多少存储空间。

可以使用 Storage 的 length 属性,对存储容量进行测算。

以 localStorage 为例:

letstr ="0123456789";
lettemp ="";
// 先生成一个 10KB 的字符串
while(str.length !== 10240) {
str = str +"0123456789";
// 清空
localStorage.clear();
// 计算总量
const computedTotal = () => {
returnnewPromise((resolve) => {
// 往 localStorage 中累积存储 10KB
const timer = setInterval(() => {
try{
localStorage.setItem("temp", temp);
}catch(e) {
// 报错说明超出最大存储
resolve(temp.length / 1024);
clearInterval(timer);
// 统计完记得清空
localStorage.clear();
temp += str;
}, 0);

// 计算使用量
const computedUse = () => {
letcache = 0;
for(letkeyinlocalStorage) {
if(localStorage.hasOwnProperty(key)) {
cache += localStorage.getItem(key).length;

return(cache / 1024).toFixed(2);

(async () => {
const total = await computedTotal();
letuse ="0123456789";
for(leti = 0; i < 1000; i++) {
use +="0123456789";
localStorage.setItem("use", use);
const useCache = computedUse();
console.log(`最大容量${total}KB`);
console.log(`已用${useCache}KB`);
console.log(`剩余可用容量${total - useCache}KB`);

可见在 Chrome 浏览器下,localStorage 有 5M 容量:



5、用好本地存储的一些建议

在某些特殊场景下,需要存储大数据,为了更好的利用 Storage 的存储空间,可以采取以下解决方案,但不应该过于频繁地将大量数据存储在 Storage 中,因为在写入数据时,会对整个页面进行阻塞(不推荐这种方式)。

5.1压缩数据

可以使用数据压缩库对 Storage 中的数据进行压缩,从而减小数据占用的存储空间。

eg:使用 lz-string 库的 compress() 函数将数据进行压缩,并将压缩后的数据存储到 localStorage 中。

const LZString = require("lz-string");
const data ="This is a test message";
// 压缩
const compressedData = LZString.compress(data);
localStorage.setItem("test", compressedData);
// 解压
const decompressedData = LZString.decompress(localStorage.getItem("test"));

5.2分割数据

将大的数据分割成多个小的片段存储到 Storage 中,从而减小单个数据占用的存储空间。

eg:将用户数据分割为单项存储到 localStorage 中。

for(const keyinuserInfo) {
localStorage.setItem(key, userInfo[key]);



5.3取消不必要的数据存储

可以在代码中取消一些不必要的数据存储,从而减小占用空间。

eg:只存储用到的用户名、公司主体和后端所在环境字段信息。

for(const keyinuserInfo) {
if(["userName","legalEntityName","isOnline"].includes(key)) {
localStorage.setItem(key, userInfo[key]);



5.4设置过期时间

localStorage 是不支持过期时间的,在存储信息过多后,会拖慢浏览器速度,也会因为浏览器存储容量不够而报错,可以封装一层逻辑来实现设置过期时间,以达到清理的目的。

// 设置
functionset(key, value){
const time =newDate().getTime();//获取当前时间
localStorage.setItem(key, JSON.stringify({value, time}));//转换成json字符串
// 获取
functionget(key, exp){
// exp 过期时间
const value = localStorage.getItem(key);
const valueJson = JSON.parse(value);
//当前时间 - 存储的创建时间 > 过期时间
if(newDate().getTime() - valueJson.time > exp){
console.log("expires");//提示过期
}else{
console.log("value:"+ valueJson.value);

6、实践应用中的案例参考

6.1使用习惯记录

用来缓存一些筛选项数据,保存用户习惯信息,起到避免多次重复操作的作用。

eg:在 beetle 工程列表中,展示了自己权限下所有 beetle 的项目,对于参与项目多和参与项目少的人,操作习惯是不同的,由此,记录收藏功能状态解决了这一问题,让筛选项记住用户选择,方便下次使用。





在开发使用中,直接获取localStorage.getItem('isFavor')作为默认值展示,切换后使用localStorage.setItem()方法更新保存内容。

// 获取
const isFavor = localStorage.getItem('isFavor');
this.state = {
isFavor: isFavor !==null? Number(isFavor) : EngineeringTypeEnum.FAVOR,
// 展示默认值
placeholder='筛选收藏的工程'
onChange={(e) =>this.changeFavor(e)}
{...searchSmallFormProps}
{EngineeringTypeEnum.property.map(e => ())}
// 变更
changeFavor = (e) => {
localStorage.setItem('isFavor', e);
this.setState({ isFavor: e });

6.2首次打开提示

用来缓存用户导览,尤其是只需要出现一次的操作说明弹窗等。

eg:当第一次或者清空缓存后登录,页面需要出现操作指南和用户手册的弹窗说明。



在开发使用中,注意存储的数据类型为 string,转成布尔值是为了在插件中方便控制弹窗的显示隐藏。

// 获取
const operationVisible = localStorage.getItem('operationVisible');
this.state = {
operationVisible: operationVisible ===null|| operationVisible ==='true'?true:false,
// 控制展示
title='操作指南'
open={this.state.operationVisible}
onCancel={() => {
this.setState({ operationVisible:false});
localStorage.setItem('operationVisible',false);
footer={null}
destroyOnClose={true}

动作
接口 》 用例 》 用例集,3级结构满足不了后续的使用,因此增加【动作】这一层级,【动作】是接口测试的最小单元,多个【动作】可以组合成一个用例,多个用例可以聚合为用例集;


6.3减少重复访问接口

在浏览页面时,会遇到一些经常访问但返回数据不更新的接口,这种特别适合用做页面缓存,只在页面打开的时候访问一次,其他时间获取缓存数据即可。

eg:在我们的一些内部系统中,用户信息是每个页面都要用到的,尤其是 userId 字段,会与每个获取数据接口挂钩,但这个数据是不会变的,一直请求是没有意义的,为减少接口的访问次数,可以将主要数据缓存在 localStorage 内,方便其他接口获取。

7、本文小结

希望通过此篇文章,可以让大家了解 Web Storage 在浏览器数据存储和读取的相关操作,以及相关事件和限制。

它可以用于保存用户的偏好设置、表单数据等,在开发中使用可以方便的存储和读取数据,提高用户体验。当然,在使用时需要特别注意它的限制,以及在存储、读取和删除数据过程中的错误处理。

8、参考资料

[1]新手入门贴:史上最全Web端即时通讯技术原理详解

[2]Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE

[3]一文读懂前端技术演进:盘点Web前端20年的技术变迁史

[4]Web端即时通讯基础知识补课:一文搞懂跨域的所有问题!

[5]Web端即时通讯实践干货:如何让你的WebSocket断网重连更快速?

[6]WebSocket从入门到精通,半小时就够!

[7]WebSocket硬核入门:200行代码,教你徒手撸一个WebSocket服务器

[8]长连接网关技术专题(四):爱奇艺WebSocket实时推送网关技术实践

[9]网页端IM通信技术快速入门:短轮询、长轮询、SSE、WebSocket

[10]搞懂现代Web端即时通讯技术一文就够:WebSocket、socket.io、SSE

[11]IM跨平台技术学习(一):快速了解新一代跨平台桌面技术——Electron

[12]Wasm在即时通讯IM场景下的Web端应用性能提升初探

[13]一套海量在线用户的移动端IM架构设计实践分享(含详细图文)

[14]一套亿级用户的IM架构技术干货(上篇):整体架构、服务拆分等

[15]一套亿级用户的IM架构技术干货(下篇):可靠性、有序性、弱网优化等

[16]从新手到专家:如何设计一套亿级消息量的分布式IM系统

[17]新手入门一篇就够:从零开发移动端IM


(本文已同步发布于:http://www.52im.net/thread-4745-1-1.html)

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
现在是1月8号中午,刚刚传来一个惊天大消息,又要来大动作吗?

现在是1月8号中午,刚刚传来一个惊天大消息,又要来大动作吗?

股市皆大事
2025-01-08 10:16:38
案例:北京一女教授在家养病长达10年,民警进门后,当场愣在原地

案例:北京一女教授在家养病长达10年,民警进门后,当场愣在原地

兰姐说故事
2025-01-02 20:00:06
正式退出,欧文做出选择,官宣决定,独行侠批准,东契奇祝福

正式退出,欧文做出选择,官宣决定,独行侠批准,东契奇祝福

东球弟
2025-01-07 10:59:50
重拾信心,探花秀谢泼德G联赛首战33中17狂轰49分5板6助3断

重拾信心,探花秀谢泼德G联赛首战33中17狂轰49分5板6助3断

懂球帝
2025-01-08 11:18:38
纽卡7000万签➡️1.8亿卖?伊萨克近15场14球,传统豪门进个遍

纽卡7000万签➡️1.8亿卖?伊萨克近15场14球,传统豪门进个遍

直播吧
2025-01-08 08:59:19
女儿想要一个单独的房间,老人一人一个房间,让谁让出房间都不合适

女儿想要一个单独的房间,老人一人一个房间,让谁让出房间都不合适

张晓磊
2025-01-06 07:55:36
演员王星获救后,透露园区情况, 许好宁、林美玲的家人紧急求助

演员王星获救后,透露园区情况, 许好宁、林美玲的家人紧急求助

桃源心语
2025-01-08 07:36:53
格局拉满!刘强东给乡亲拜年:我是你们的大强子

格局拉满!刘强东给乡亲拜年:我是你们的大强子

看晓天下事
2025-01-07 19:39:17
1比2爆大冷一轮游!26岁国羽名将状态低迷,未来咋当领军人物?

1比2爆大冷一轮游!26岁国羽名将状态低迷,未来咋当领军人物?

体坛知道分子
2025-01-08 06:30:03
美国法国特种部队联合伞降训练 M110A1半自动狙击步枪低调亮相

美国法国特种部队联合伞降训练 M110A1半自动狙击步枪低调亮相

hawk26讲武堂
2025-01-08 12:59:23
“比基尼京剧” 照片被曝惹争议:吃瓜群众直呼辣眼睛!

“比基尼京剧” 照片被曝惹争议:吃瓜群众直呼辣眼睛!

书画艺术收藏
2025-01-05 19:20:03
人到七,八十岁,你会发现最终能让你快乐幸福的就是这4点

人到七,八十岁,你会发现最终能让你快乐幸福的就是这4点

娱乐洞察点点
2025-01-06 22:26:55
汪涵年近五旬沦落街头卖艺?近照沧桑像素人,与网红坐路边卖水果

汪涵年近五旬沦落街头卖艺?近照沧桑像素人,与网红坐路边卖水果

扒星人
2025-01-08 12:10:58
这位大姐真是的,都已经这样了,还开着美颜上镜。

这位大姐真是的,都已经这样了,还开着美颜上镜。

人情皆文史
2024-08-02 22:45:52
为什么我们要在这个时候宣布黄岩岛主主权?

为什么我们要在这个时候宣布黄岩岛主主权?

书中自有颜如玉
2025-01-08 10:01:03
马卡:21岁的贝林厄姆在皇马表现出色,风格特点都类似齐达内

马卡:21岁的贝林厄姆在皇马表现出色,风格特点都类似齐达内

直播吧
2025-01-07 14:16:10
网传南京地铁三期已获批,南京发改:还未收到批复消息

网传南京地铁三期已获批,南京发改:还未收到批复消息

现代快报
2025-01-07 19:45:33
上个月,我去了趟拉萨回来后,我只想说,能不去就尽量不去

上个月,我去了趟拉萨回来后,我只想说,能不去就尽量不去

猫小狸同学
2024-11-28 13:45:03
79岁老人坦言:雇住家保姆养老,就是一场残酷无情的金钱交易

79岁老人坦言:雇住家保姆养老,就是一场残酷无情的金钱交易

烙任情感
2025-01-07 12:12:58
8连败!0比11惨败!16岁张本美和差距明显,网友:名气大于实力

8连败!0比11惨败!16岁张本美和差距明显,网友:名气大于实力

体坛知道分子
2025-01-08 06:05:02
2025-01-08 13:35:00
即时通讯技术分享
即时通讯技术分享
即时通讯相关技术的研究与分享
422文章数 3618关注度
往期回顾 全部

科技要闻

定了!买手机,国家最高补贴500元

头条要闻

多位老师回应“刘强东发10万现金” 师生旧合照披露

头条要闻

多位老师回应“刘强东发10万现金” 师生旧合照披露

体育要闻

消失3年后,国乒冠军成为一名大学老师

娱乐要闻

王星假装顺从保命,采访时看泰警脸色

财经要闻

重要通知!以旧换新加力扩围

汽车要闻

10万元级无图智驾 悦也PLUS全路况实测

态度原创

家居
旅游
本地
房产
公开课

家居要闻

诠释未来 置身星际之间

旅游要闻

游客投诉在九寨沟景区买到假银饰 官方:属实

本地新闻

我和我的家乡|一“津”到底,美在不言中

房产要闻

惊艳白鹅潭的“鼎豪瑧品”,竟是保利造!

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版