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

相关推荐
头茬韭菜6 分钟前
4.9 SSRF 防护 — Web 工具的出站安全与私有 IP 拦截
前端·tcp/ip·安全
Cobyte16 分钟前
模板 DSL 解析器中的状态机设计
前端·javascript·vue.js
颜酱19 分钟前
# 02 | 搭骨架:用 LangGraph 编排 12 步工作流(思路)
前端·人工智能·后端
颜酱20 分钟前
02 | 搭骨架:用 LangGraph 编排 12 步工作流
前端·人工智能·后端
刘卓航众创芯云服务部1 小时前
Kimi K3复杂任务实测:我把团队最头疼的三个场景全跑了一遍
前端
cll_8692418912 小时前
一个好看的Wordpress博客文字css样式
前端·css·ui
武子康2 小时前
Shippy:确定性工具、会话级 Sandbox 与 Live-Data Eval(4 类收敛 + 7 步实现方案 + 6 类评测指标)
前端·人工智能·后端
糖果店的幽灵2 小时前
langgraph分支之 - 动态分支(Dynamic Branch)
java·前端·javascript·人工智能·langgraph
meilindehuzi_a2 小时前
Workflow 与 Agent 有什么区别:从 LangChain 流水线到智能体决策
前端·人工智能
三翼鸟数字化技术团队2 小时前
一种前端大屏适配方案
前端·css