You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue组合式函数用useFetch为何不隔离?Nuxt3场景BUG求助

问题:Nuxt3组合式函数中useFetch请求结果相互覆盖

技术栈与场景

使用Vue 3 + Nuxt 3 + Vite开发项目,编写了useCheckerRole组合式函数用于根据用户角色判断组件是否可渲染:

useCheckerRole 组合式函数

export function useCheckerRole(policies){
  const {data, error} = await useFetch("/api/role-checker", {
    method: "POST",
    body: policies
  })

  if(data.value) {
    return data.value
  }

  if(error.value) {
    throw new Error("an error occured");
  }
}

调用方式

const policies = await useCheckerRole([
  {
   component_ask: 'some-button',
   role_ask: 'administrator'
  }
])

接口返回示例

[{
  component_ask: 'some-button',
  role_ask: 'administrator',
  status: 'approved'
}]

BUG表现

同一页面的两个组件同时调用useCheckerRole时,请求结果相互覆盖:

  • TopBar.vue传入自身规则,却拿到了ChildPage.vue的请求结果
  • ChildPage.vue结果正常,TopBar的结果被覆盖

TopBar.vue代码

const policies = await useCheckerRole([
  {
   component_ask: 'top-bar-button',
   role_ask: 'administrator'
  }
]).catch((error) => { /* 错误处理 */ })

console.log("topBar Policies result", policies)

ChildPage.vue代码

const policies = await useCheckerRole([
  {
   component_ask: 'child-page-button',
   role_ask: 'administrator'
  },
  {
   component_ask: 'child-page-other-button',
   role_ask: 'administrator'
  },
]).catch((error) => { /* 错误处理 */ })

console.log("Child Policies result", policies)

实际结果与预期

  • TopBar实际拿到的结果(和ChildPage一致):
[
  {
   component_ask: 'child-page-button',
   role_ask: 'administrator',
   status: "approved"
  },
  {
   component_ask: 'child-page-other-button',
   role_ask: 'administrator',
   status: "rejected"
  },
]
  • TopBar应得的结果:
[
  {
   component_ask: 'top-bar-button',
   role_ask: 'administrator',
   status: "approved"
  },
]

解决方案

问题原因

Nuxt的useFetch默认仅根据请求URL生成缓存键,POST请求的请求体(body)不会被纳入缓存键计算逻辑。这导致两个不同body但相同URL的POST请求会共享同一个缓存,后发起的请求结果会覆盖先发起的。

修复方法

给每个useFetch请求添加唯一缓存键,基于传入的policies生成,确保不同请求的缓存相互隔离。

修改后的useCheckerRole函数:

export function useCheckerRole(policies){
  // 基于请求体生成唯一缓存键,避免不同请求共享缓存
  const fetchKey = JSON.stringify(policies)
  const {data, error} = await useFetch("/api/role-checker", {
    method: "POST",
    body: policies,
    key: fetchKey // 显式指定唯一缓存键
  })

  if(data.value) {
    return data.value
  }

  if(error.value) {
    throw new Error("权限校验请求出错");
  }
}

补充说明

  • 使用JSON.stringify(policies)生成键,能确保只要policies内容不同,缓存键就不同,彻底避免冲突
  • 这种方式既解决了覆盖问题,又保留了相同policies请求的缓存复用能力,减少重复请求
  • 如果完全不需要缓存,也可以设置cache: false,但不推荐,缓存能有效提升页面性能

内容的提问来源于stack exchange,提问作者Egy Ramschie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 19:28:24