封装的useFetchToken组合式函数调用两次出现数据覆盖问题求助
问题解决:两次调用自定义useFetchToken导致数据覆盖
问题场景
封装了自动添加请求头的组合式函数useCommon:
export const useCommon = () => { async function useFetchToken(api: string, option: useFetchTokenTyle){ const autoOption:any = { headers: (option.headers) ?? { Authorization: 'Bearer ' + ado_token.value } } // 省略其他逻辑 return await useFetch(api, {...option,...autoOption}) } return { useFetchToken } }
在同一组件中两次调用该函数:
<script setup lang="ts"> const { useFetchToken } = useCommon() let {data:category_lists, refresh:cateRefresh} = await useFetchToken('/api/action', { baseURL: CATEGORY_API, method: 'post', body: { action: 'DoSomeThing', } }) let {data:section_lists, refresh:sectionRefresh} = await useFetchToken('/api/action', { baseURL: CATEGORY_API, method: 'post', body: { action: 'DoSomeThing2', } }) </script>
出现异常:第一次请求返回的category_lists被第二次调用的结果覆盖,删除第二次调用后数据显示正常,直接使用原生useFetch无此问题。
原因分析
Nuxt的useFetch基于useAsyncData实现,默认会根据请求的API路径、请求方法、baseURL等生成缓存key,但默认key不会包含请求body的内容。两次调用的API路径、method、baseURL完全一致,仅body不同,导致useFetch认为是同一个请求,复用了同一个状态对象,第二次请求的结果因此覆盖了第一次的。
解决方案
有两种可靠的解决方式:
方式1:调用时手动传入唯一key
在调用useFetchToken时,给每个请求指定不同的key参数,确保缓存状态唯一:
<script setup lang="ts"> const { useFetchToken } = useCommon() let {data:category_lists, refresh:cateRefresh} = await useFetchToken('/api/action', { baseURL: CATEGORY_API, method: 'post', body: { action: 'DoSomeThing', }, key: 'category-fetch' // 指定唯一标识key }) let {data:section_lists, refresh:sectionRefresh} = await useFetchToken('/api/action', { baseURL: CATEGORY_API, method: 'post', body: { action: 'DoSomeThing2', }, key: 'section-fetch' // 指定另一唯一标识key }) </script>
方式2:在封装函数中自动生成唯一key
修改useFetchToken,根据请求的body内容(或其他唯一标识)自动生成key,无需用户手动传入:
export const useCommon = () => { async function useFetchToken(api: string, option: useFetchTokenTyle){ // 基于api、method和body生成唯一key const requestKey = `${api}-${option.method}-${JSON.stringify(option.body)}` const autoOption:any = { headers: (option.headers) ?? { Authorization: 'Bearer ' + ado_token.value }, key: requestKey // 自动注入唯一key } // 省略其他逻辑 return await useFetch(api, {...option,...autoOption}) } return { useFetchToken } }
注意:如果body中包含无法序列化的内容(如函数),需要调整key的生成逻辑,比如提取body中的关键唯一字段来拼接key。
内容的提问来源于stack exchange,提问作者Lawyer Kenny
相关产品推荐
相关产品推荐

