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

相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学2 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端