为什么 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 辅助生成,并由作者整理审核。

相关推荐
kyriewen12 小时前
我手写了一个 EventEmitter,面试官追问了 6 个问题——第 4 个我没答上来
前端·javascript·面试
IT_陈寒12 小时前
Java的Date类又坑了我一次,改用时间戳真香
前端·人工智能·后端
小林攻城狮12 小时前
使用 Transport 节流解决 Vercel AI SDK 流式渲染卡死问题
前端·react.js
前端缘梦13 小时前
告别 TS 运行时类型漏洞!Zod 完整入门实战教程(前端 / 全栈必备)
前端·react.js·全栈
the_answer13 小时前
Webpack vs Vite 深度对比分析
前端·webpack
转转技术团队13 小时前
验证码识别实战:前端不写页面,改训模型了?
前端
MomentYY13 小时前
Temperature:AI 的“脑洞旋钮”
前端·llm·ai编程
远航_13 小时前
OpenSpec 完整详细介绍
前端·后端
召钱熏14 小时前
状态枚举正确≠渲染正确:一个语音按钮的状态机边界修复实录
android·前端
SkyWalking中文站14 小时前
认识 Horizon UI · 1/17:SkyWalking 新一代可观测性控制台
运维·前端·监控