网站建设用户需求表,网站页面设计报价模板,浏览器下载,比百度好用的搜索引擎在前端开发中#xff0c;http请求层的封装可以极大提升代码的复用性和可维护性#xff0c;本文将完整的用axios封装接口请求#xff0c;配置请求与响应拦截器#xff0c;封装统一的请求方法全过程。封装的目的和思路在项目直接用axios发送请求当然没问题#xff0c;但是如… 在前端开发中http请求层的封装可以极大提升代码的复用性和可维护性本文将完整的用axios封装接口请求配置请求与响应拦截器封装统一的请求方法全过程。 封装的目的和思路 在项目直接用axios发送请求当然没问题但是如果不做封装每个请求都需要手动处理token,错误提示等逻辑容易重复缺乏统一的loading处理逻辑不同组件可以用不一致的方式调用axios增加维护成本。业务错误比如登录失败权限不足不集中处理用户体验差。 所以我们统一封装是为了实现这些目标。 1.封装Axios实例设置baseURL和超时。 2.添加请求拦截器自动加token显示Loading 3.添加响应拦截器 统一处理错误隐藏loading 4 暴露统一的get/post等请求方法 5.支持类型推导泛型 step1:安装Axios npm install axios step2创建Axios实例并且封装基础配置
// api/request.ts
import axios, { AxiosError } from axios
import { message } from antd
import { showLoading, hideLoading } from ./loadingconst instance axios.create({baseURL: /api, // 接口统一前缀timeout: 8000, // 超时时间timeoutErrorMessage: 请求超时请稍后再试,withCredentials: false, // 是否携带 Cookie
})
为什么要用 axios.create可以创建多个实例分别管理不同的 baseURL如主站与后台接口。不影响全局 axios互不干扰。step3请求拦截器
instance.interceptors.request.use((config) {showLoading()const token localStorage.getItem(token)if (token) {config.headers.Authorization Token:: token}return { ...config }},(error: AxiosError) {return Promise.reject(error)}
) 请求拦截器做了什么 1.请求前显示 loading配合 Ant Design 的 Spin 2.自动从 localStorage 中读取 token统一加入到请求头中 3.你也可以添加其他自定义 headers例如用户 ID、语言偏好等step4响应拦截器--统一 错误处理以及成功返回data
instance.interceptors.response.use((response) {hideLoading()const data response.dataif (data.code 500001) {// 登录失效message.error(data.msg || 身份已过期请重新登录)localStorage.removeItem(token)return Promise.reject(data)} else if (data.code ! 0) {// 业务错误message.error(data.msg || 请求错误请稍后重试)return Promise.reject(data)}return data.data // 请求成功返回业务数据},(error: AxiosError) {hideLoading()message.error(error.message || 服务器异常请稍后重试)return Promise.reject(error)}
) 拦截器可能有人不理解概念。这里把概念放在这里。 axios.interceptors.request.use 是 Axios 提供的 API用来设置请求发出前的统一处理逻辑。它接收两个回调函数第一个是处理请求体 config 的我们通常在这里加上 token、显示 loading处理完之后必须返回 config 否则请求会被中断。 第二个是请求配置阶段发生错误时的处理函数比如拦截器中抛出异常这个函数里我们一般把错误通过 Promise.reject 抛出去供 .catch 捕获使用。 Axios 的响应拦截器也接收两个回调函数第一个是响应成功时调用它的参数是 response从中我们可以提取 response.data然后判断自定义的 code 字段来决定是 token 过期、业务出错还是成功。如果 token 过期或失败会弹出错误提示并通过 Promise.reject 抛出错误。 第二个回调函数是响应失败如网络错误、404、500时触发的我们可以统一显示“服务器异常”等提示也用 Promise.reject 抛出错误供组件用 .catch() 捕获。 后端返回的 data 结构通常如下{code: 0,msg: 成功,data: { userInfo: { ... } }} 然后我们就可以明显看到我们请求拦截器实际上就是config这个请求体在发送之前我们去加一些逻辑去处理我们的config请求体。比如头部加上Authorization属性值为token把我们的token加上去。还有第二个回调函数就是把错误作为Promise实例的rejecterror扔出去这样我们组件可以用.catch捕捉。 响应拦截器同理response就是我们的响应体。我们响应体在到组件接收之前我们对响应体做一些处理比如我们不需要响应体我们只是想要里面的data.data那么成功就返回data.data如果token过期了久调用message这是个组件然后.error显示错误比如token过期了。总之只要有响应体一定会返回data给到我们的组件。如果响应拦截的时候就发现报错了那么就reject扔出error组件.catch捕获。step5:封装统一请求方法泛型
export default {getT(url: string, params?: object): PromiseT {return instance.get(url, { params })},postT(url: string, params?: object): PromiseT {return instance.post(url, params)},// 后续可添加 put、delete 等
} 为什么要用泛型 T调用接口时能获得接口返回值的类型提示增强类型安全调用时直接写 const res await api.getYourType(...)step6如何使用封装后的请求
// api/user.ts
import request from ./requestexport const getUserInfo () {return request.get{ name: string; age: number }(/user/info)
}通过引入对象的形式直接调用里面的方法就可以了然后声明泛型也就是我们如果需要返回值的话声明返回值的类型。然后后面是传过去的url访问的接口。实际上访问的地址是baseUrl我们传过去的url。 总结