为什么 Pinia + localForage 持久化后,页面初始化拿不到数据?

最近在给 Pinia 实现持久化时遇到了一个问题:

ini 复制代码
const userStore = useUserStore();

console.log(userStore.token);

明明数据已经保存到 localForage 中,但页面首次加载时拿到的却是默认值。

而在异步代码中:

scss 复制代码
await nextTick();

console.log(userStore.token);

或者:

javascript 复制代码
setTimeout(() => {
  console.log(userStore.token);
}, 100);

却能够正常获取到持久化后的数据。

问题原因

问题的根源在于:

Pinia 的初始化是同步的,而 localForage 的数据读取是异步的。

当执行:

ini 复制代码
const userStore = useUserStore();

时,Pinia 会立即创建 Store:

scss 复制代码
创建 Store
↓
执行 state()
↓
返回 Store

此时 Store 中的数据还是默认值:

css 复制代码
{
  token: ""
}

而 localForage 底层使用的是 IndexedDB,读取数据需要异步执行:

ini 复制代码
const cache = await localforage.getItem("user");

因此会出现下面的执行顺序:

perl 复制代码
创建 Store
↓
返回默认 state
↓
页面开始渲染
↓
localForage 开始读取缓存
↓
缓存读取完成
↓
store.$patch(cache)

也就是说:

复制代码
Store 已创建
≠
持久化数据已恢复

所以页面初始化时拿到的是默认值,而不是缓存中的值。

为什么 localStorage 没有这个问题?

因为 localStorage 是同步 API:

ini 复制代码
const cache = localStorage.getItem("user");

执行流程:

复制代码
读取缓存
↓
恢复数据
↓
返回 Store

Store 返回时数据已经恢复完成,因此组件中能够直接获取到最新状态。

一个常见误区

很多人会这样写:

ini 复制代码
pinia.use(async ({ store }) => {
  const cache = await localforage.getItem(store.$id);

  if (cache) {
    store.$patch(cache);
  }
});

以为加了 async/await 后 Pinia 会等待数据恢复。

实际上并不会。

Pinia 插件本身是同步执行的,Store 不会等待异步任务结束才创建完成。

所以即使使用:

dart 复制代码
pinia.use(async () => {})

也无法阻止 Store 先返回。

总结

这个问题本质上不是 Pinia 的问题,也不是 localForage 的问题,而是同步初始化与异步恢复之间的时间差导致的。

复制代码
Pinia Store 创建:同步

localForage 数据读取:异步

因此当页面首次渲染时:

复制代码
Store 已存在
数据未恢复

而等异步读取完成后:

复制代码
Store 已存在
数据已恢复

这就是为什么在页面初始化阶段拿不到值,而在异步代码中却能够正常获取到值的原因。

本文部分内容借助 AI 辅助生成,并由作者整理审核。

相关推荐
扫一屋28 分钟前
Element Plus 源码级深度定制:不 Fork、不改包,用 Vite 插件实现组件行为运行时改造
前端
BigTopOne1 小时前
KOOM 学习计划
前端
自进化Agent智能体2 小时前
Hermes 技能系统详解——安装、使用与浏览
前端
JieE2122 小时前
前端不等人:用 Mock 接口工程让 React 应用独立起飞
前端·react.js·面试
用户355856959022 小时前
HTTPS到底会不会拖慢网站速度?TLS握手原理与性能优化实战
前端
xywww1682 小时前
真实后台页实测:Opus 5 看图写前端的可用边界在哪
linux·服务器·前端·数据库·人工智能·gpt
小小尚@3 小时前
AE脚本-AE Actions v1.1.8 操作动作记录器
开发语言·前端·javascript·jupyter·postman
大家的林语冰3 小时前
👍 超越 ESLint,Oxc 优先采用 TypeScript 7,Rust 和 Go 梦幻联动!
前端·javascript·typescript
樊小肆4 小时前
# 你还在等DeepSeek官方 agent Harness‌? 来试试 DeepSeeker-Code吧
前端·人工智能·后端
樊小肆4 小时前
2568 万 token 才花 2 块 2:聊聊 DeepSeeker-Code 怎么吃满上下文缓存
前端·人工智能·后端