前端偏好设置的本地存储:校验、版本与失败回退
为一个轻量网页保存主题、专注时长等偏好,localStorage 很方便:保存字符串后,刷新页面仍可读取。但“读到了字符串”并不意味着可以直接使用。旧版本留下的字段、格式损坏的 JSON,以及浏览器拒绝存储的情况,都需要有清楚的处理规则。
一、先确定数据格式,再使用读取结果
下面用一个独立示例保存主题与分钟数。约定主题只能是 light 或 dark,时长是一到一百八十之间的整数,v 表示存储格式版本。读取后只取已知字段,不把整个对象合并到页面配置中。
JSON.parse 只负责解析语法。字符串形式的“25”、超过范围的数字、缺失字段,即使能成功解析,也不符合这里的业务规则。遇到这些情况,返回一份新的默认配置即可,让页面继续可用。
const KEY = 'small-tool:prefs';
const defaults = () => ({ theme: 'light', minutes: 25 });
const valid = p => p !== null && typeof p === 'object'
&& ['light', 'dark'].includes(p.theme)
&& Number.isInteger(p.minutes)
&& p.minutes >= 1 && p.minutes <= 180;
function readPrefs(getStorage = () => window.localStorage) {
try {
const p = JSON.parse(getStorage().getItem(KEY) ?? 'null');
if (p?.v !== 1 || !valid(p)) return defaults();
return { theme: p.theme, minutes: p.minutes };
} catch {
return defaults();
}
}
function savePrefs(prefs, getStorage = () => window.localStorage) {
if (!valid(prefs)) return false;
try {
const data = { v: 1, theme: prefs.theme, minutes: prefs.minutes };
getStorage().setItem(KEY, JSON.stringify(data));
return true;
} catch {
return false;
}
}
二、把获取存储对象也放进异常处理
示例把 getStorage 写成函数,调用它的位置在 try 内部。这样不只捕获 getItem、setItem 的异常,也能处理获取 window.localStorage 时就被浏览器拒绝的情况。如果直接把 localStorage 作为默认参数求值,错误可能在进入函数体之前就发生。
正常调用时可以直接使用 readPrefs()。保存时先判断 savePrefs({ theme: 'dark', minutes: 45 }) 的返回值:成功才显示“已保存”;失败则提示“设置仅在本次页面中生效,未保存到本地”,同时保留当前内存中的设置。
三、回退默认值时保留原始记录
readPrefs 只读取,不会删除或覆盖格式异常的旧记录。不要在初始化后立刻自动保存默认值,否则一旦读取失败,原来的数据就可能被覆盖。等用户主动修改设置时再保存;若未来需要支持旧格式,应增加明确的迁移函数,而不是只改版本号。
四、用八种输入核对边界
本例在浏览器中用内存存储对象和故障对象进行了八项验证:没有记录、损坏的 JSON、不支持的版本、字符串时长、越界时长、获取存储对象被拒绝、写入抛出配额异常,以及合法配置保存后重新读取。前五项均回退默认配置;拒绝访问时读取回退、保存返回 false;模拟配额异常时保存返回 false;正常往返保持 dark 与 45 的值不变。
其中权限和配额场景使用抛错对象模拟,验证的是应用的降级分支,并未实际耗尽浏览器存储。测试时注入存储访问函数,也能避免碰到页面中已有的数据。
这套方式适合主题、显示选项和少量偏好设置。localStorage 按来源隔离,也不负责跨设备同步;更换域名或浏览器后,应当允许用户从默认配置重新开始。读取有校验、写入有结果、失败有反馈,才能让简单的本地保存功能更容易维护。
- 点赞
- 收藏
- 关注作者
评论(0)