在前端项目中,和后台交互获取数据这块,我们通常使用的是axios库,axios是一个基于
promise
的HTTP库,可运行在client
端和server
端。
虽然axios的使用已经很方便了,但是在实际项目中,为了接口的规则一致,来创建一个统一管理的全局方法以达到简化操作的目的。
一,安装axios
yarn add axios -D
// 或者
npm i axios -D
二,创建axios实例
# 项目src下新建utils/request.ts
import axios from 'axios'
axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
export default axios
三,添加拦截器
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
return response;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
});
3.1 修改axios实例的请求拦截器(在请求头里携带Token)
instance.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
const userStore = useUserStore()
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error)
}
)
3.2 添加响应拦截器(返回状态码)
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
loadingInstance.close();
removePending(response.config);
const errorCode = response?.data?.errorCode;
switch (errorCode) {
case '401':
// 根据errorCode,对业务做异常处理(和后端约定)
break;
default:
break;
}
return response;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
loadingInstance.close();
const response = error.response;
// 根据返回的http状态码做不同的处理
switch (response?.status) {
case 401:
// token失效
break;
case 403:
// 没有权限
break;
case 500:
// 服务端错误
break;
case 503:
// 服务端错误
break;
default:
break;
}
return Promise.reject(error);
});
1xx(临时响应)
表示临时响应并需要请求者继续执行操作的状态代码
2xx (成功)
表示成功处理了请求的状态码。
常见的2开头的状态码有:200 – 服务器成功返回网页
3xx (重定向)
表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向
常见的3字开头的状态码有:
301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应时,会自动将请求者转到新位置。
302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容走协商缓存。
4xx(请求错误) 这些状态代码表示请求可能出错,妨碍了服务器的处理。
常见的4字开头的状态有:404 – 请求的网页不存在k
401没权限吧.当时在我们项目里面的时候token值过期就是返回401.我在响应拦截器做了处理
5xx(服务器错误)
这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。
常见的以5开头的状态码有:
500 (服务器内部错误) 服务器遇到错误,无法完成请求。
503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
四,响应状态码401报错的处理
状态码 401 Unauthorized 代表客户端错误,指的是由于缺乏目标资源要求的身份验证凭证,发送的请求未得到满足。说人话就是“Token失效/出错”!
为了尽可能追求完美,这里的逻辑比较复杂:
① Token失效,使用路由转回登录页
② 假设在 abc 页面访问,这里发现 Token 失效了,我们使用路由转回了登录页;
重新登录成功后,体验好的app会让我回到本来访问的abc页面,并且携带可能的路径参数;
③ 实现方式:把原本的页面路径&参数全部给到query带上,重新登录成功就能完美转回了;
// 响应拦截器失败的函数内修改
function (error: AxiosError) {
// 超出 2xx 范围的状态码都会触发该函数
// 对响应错误做点什么
if (error.response?.status === 401) {
// Pinia里删除用户信息
const userStore = useUserStore()
userStore.delUser()
// 跳转登录,带上接口失效所在页面的地址,登录完成后回跳使用
router.push({
path: '/login',
query: { redirectURL: router.currentRoute.value.fullPath }
})
}
return Promise.reject(error)
}