axios 重发请求后数据如何重新渲染

2023-07-12 11:43:34 +08:00
 bhbhxy

由于 token 过期,在获取新 token 后使用 axios 重新发送之前的请求,数据也传回来了,但是现在有一个问题,列表数据无法显示了,页面的结构是这样的 index.vue

<template>
	<ChildComponent />
</template>

我是在<ChildComponent />中请求的数据:

	<template>
    	<ul>
        	<li v-for="item in list">{{item}}</li>
        </ul>
    </template>
    <script>
		const list = getDataFromApi().data
    </script>

重发请求写在拦截器里:

axios.interceptors.response.use(
	response => {
		//请求重发
        if(statusCode === 401) {
        	getNewToken()
			return axios.request(response.config);
        }
	}	
})

请求是重发了,但是组件里的list并没有接收到新数据,因此列表也没有重新渲染,请问这种情况怎么处理,或者有什么别的解决方案吗

2989 次点击
所在节点    Vue.js
36 条回复
summerLast
2023-07-12 16:36:09 +08:00
@bhbhxy 第一次的 list 是什么还是就是 401
bhbhxy
2023-07-12 16:39:35 +08:00
@shakukansp 专门为这个引入一个库是否增加开发成本
bhbhxy
2023-07-12 16:41:02 +08:00
@summerLast token 没失效是正常的,失效了才返回 401 ,这时候再去获取新 token ,然后重发之前的请求
shakukansp
2023-07-12 16:44:35 +08:00
@bhbhxy 自己写个简单的也行,但是你自己写的肯定没封装好的考虑全面
summerLast
2023-07-12 16:45:11 +08:00
@bhbhxy 建议直接 打印 ((await getDataFromApi()).data ), 看看哪块报错了,伪代码看着没有逻辑上的问题 建议 axios.request(reponse.config) 增加上 await
shakukansp
2023-07-12 16:48:13 +08:00
const useRequest = (fn) => {
const data = ref()
const send = async () => {
data.value = await fn
}

return {
data,
send
}
}
shakukansp
2023-07-12 16:48:58 +08:00
里面的 fn 加个()
wali77
2023-07-12 16:55:34 +08:00
zcf0508
2023-07-12 16:55:56 +08:00
不是响应式的问题吧,你要处理的是看下拦截器为什么没有返回数据
bhbhxy
2023-07-12 16:56:11 +08:00
@shakukansp 感谢感谢,我好像弄明白了
bhbhxy
2023-07-12 16:57:26 +08:00
@wali77 最近好用的不用梯子的 gpt 都不能访问了,感谢提供新资源🌹
shakukansp
2023-07-12 17:04:56 +08:00
@bhbhxy 这个是大概思路,实际上还要处理错误啥的
Ng8023
2023-07-12 17:07:57 +08:00
个人经验给出以下方案:
----
1. 401 可以让后端包装在 200 状态内部(后端无论如何总是返回类似这样的结构), 这样就不会走到 onRejected 里面
{code:number, message?:string, data?:any}
^^--- 401 可以在这里返回
2. 拦截到 code===401 不着急返回, 根据业务处理进行处理:
a. 发广播到登录(授权)组件重新授权(假定为异步)
b. 拿到新的授权码(token), 重新发起本次请求(AxiosResponse<T>里面能获取到请求参数)
c. 注意: 要处理无限递归授权问题, 可以给定重试次数限制

----
伪代码:
service.interceptors.response.use(
(resp: AxiosResponse<vo.R>) => {
const r = resp.data;
if (r.code === 401) {
// 检测重试上限
if (++retryTimes >= MAX_RETRY_TIMES) {
return Promise.reject("授权失败");
}

// 重新获取授权码
// 拿到授权码并保存到状态管理
await reqAuth();

// 用新授权重试
return axios(resp.config);
}

// 其他逻辑
// 业务层只处理: {code:number, data?:any, message?:string} 结构
return r;
},
(err: AxiosError) => {
// 处理错误
}
)
liberty1900
2023-07-13 00:16:16 +08:00
mingl0280
2023-07-13 01:26:22 +08:00
@bhbhxy 外部代码需要引用特定 component 的实例才能修改实例内部数据。你自己没把实例保存下来吧?我就没看见你引用 childComponent 的实例的。
webszy
2023-08-19 08:05:04 +08:00
真的很简单,想要触发 v–for 的重绘,可以修改 key

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/956106

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX