pinia 的 actions 是处理业务逻辑(含异步请求)的核心,应封装接口调用、数据转换和错误处理;推荐使用 async/await 发起请求,通过 this 访问状态,并设置 loading、统一错误处理,避免操作 dom 或路由;建议抽离 api 层、配合 typescript 类型标注及插件优化。

Pinia 的 Actions 是处理业务逻辑(包括异步请求)的核心位置,推荐把接口调用、数据转换、错误处理等都封装在 Action 里,保持 Store 的可读性和可测试性。
在 Action 中发起异步请求
直接在 Action 函数中使用 async/await,配合 fetch 或 axios 发起请求。Action 会自动支持 Promise,调用方可以 await 它。
- Store 内部通过 this 访问 state、getters 和其他 actions
- 建议请求前设置 loading 状态,请求后更新数据或捕获错误
- 避免在 action 内直接操作 DOM 或路由,保持关注点分离
示例(使用 axios):
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: null,
loading: false,
error: null
}),
actions: {
async fetchUserInfo(id) {
this.loading = true;
this.error = null;
try {
const res = await axios.get(`/api/users/${id}`);
this.userInfo = res.data;
} catch (err) {
this.error = err.response?.data?.message || '获取用户失败';
} finally {
this.loading = false;
}
}
}
});
组合多个异步操作(如串行/并行请求)
一个 Action 可以调用其他 Action,也支持 await 多个请求,适合需要依赖顺序或聚合数据的场景。
- 串行:await this.fetchProfile(); await this.fetchPosts();
- 并行:await Promise.all([this.fetchProfile(), this.fetchSettings()])
- 注意错误处理粒度——可分别 try/catch,也可统一兜底
复用请求逻辑(抽离 API 层)
不建议把 axios 配置或 URL 拼接写死在 Action 里。更合理的方式是:
- 单独建 apis/ 目录,每个模块对应一个 API 文件(如 userApi.js)
- Action 中只 import 并调用封装好的函数,专注状态变更逻辑
- 便于 mock、统一拦截、类型提示和单元测试
配合 TypeScript 提升安全性
为 Action 参数和返回值标注类型,尤其注意 Promise 的泛型:
- async fetchUser(id: string): Promise
- state 中的属性类型建议与接口对齐(如 userInfo: User | null)
- 利用 Pinia 插件(如 pinia-plugin-persistedstate)时,注意异步初始化时机










