当前位置:   article > 正文

Vue3+TS封装axios

vue3+ts封装axios

1.实现最基础的封装

将其封装为一个类,而不是一个函数的原因是因为类可以创建多个实例,适用范围更广,封装性更强一些。

index.ts 

  1. // index.ts
  2. import axios from 'axios'
  3. import type { AxiosInstance, AxiosRequestConfig } from 'axios'
  4. class ZJRequest {
  5. // axios 实例
  6. // 定义一个axion实例属性
  7. instance: AxiosInstance
  8. // 利用构造函数要求传入使用 ZJRequest类时传入参数
  9. constructor(config: AxiosRequestConfig) {
  10. // 把axios实例赋给instance
  11. this.instance = axios.create(config)
  12. }
  13. request(config: AxiosRequestConfig) {
  14. return this.instance.request(config)
  15. }
  16. }
  17. export default ZJRequest

2.拦截器封装

首先我们封装一下拦截器,这个拦截器分为三种:

  • 类拦截器
  • 实例拦截器
  • 接口拦截器

接下来我们就分别实现这三个拦截器。

类拦截器

类拦截器比较容易实现,只需要在类中对axios.create()创建的实例调用interceptors下的两个拦截器即可,实例代码如下:

  1. // index.ts
  2. constructor(config: AxiosRequestConfig) {
  3. this.instance = axios.create(config)
  4. // 添加所有的实例都有的拦截器
  5. this.instance.interceptors.request.use(
  6. (config) => {
  7. // console.log('所有的实例都有的拦截器:请求拦截成功')
  8. if (this.showLoading) {
  9. this.loading = ElLoading.service({
  10. lock: true,
  11. text: '正在请求数据....',
  12. background: 'rgba(0,0,0,0.5)'
  13. })
  14. }
  15. return config
  16. },
  17. (err) => {
  18. // console.log('所有的实例都有的拦截器:请求拦截失败')
  19. return err
  20. }
  21. )
  22. this.instance.interceptors.response.use(
  23. (res) => {
  24. // console.log('所有的实例都有的拦截器:响应拦截成功')
  25. // 将loading移除
  26. this.loading?.close()
  27. // 将loading移除
  28. // this.loading?.close()
  29. const data = res.data
  30. if (data.returnCode === '-1001') {
  31. console.log('请求失败,错误信息')
  32. } else {
  33. return data
  34. }
  35. },
  36. (err) => {
  37. console.log('所有的实例都有的拦截器:响应拦截失败')
  38. // 将loading移除
  39. this.loading?.close()
  40. if (err.response.status === 404) {
  41. console.log('404的错误')
  42. }
  43. return err
  44. }
  45. )
  46. }

实例拦截器

实例拦截器是为了保证封装的灵活性,因为每一个实例中的拦截后处理的操作可能是不一样的,所以在定义实例时,允许我们传入拦截器。

首先我们定义一下interface,方便类型提示,代码如下:

  1. constructor(config: HYRequestConfig) {
  2. this.instance = axios.create(config)
  3. this.showLoading = config.showLoading ?? true
  4. // 实例拦截器
  5. this.interceptors = config.interceptors
  6. this.instance.interceptors.request.use(
  7. this.interceptors?.requestInterceptor,
  8. this.interceptors?.requestInterceptorCatch
  9. )
  10. this.instance.interceptors.response.use(
  11. this.interceptors?.responseInterceptor,
  12. this.interceptors?.responseInterceptorCatch
  13. )
  14. }

接口拦截

  1. request<T>(config: HYRequestConfig<T>): Promise<T> {
  2. return new Promise((resolve, reject) => {
  3. // 1.单个请求对请求config的处理
  4. if (config.interceptors?.requestInterceptor) {
  5. config = config.interceptors.requestInterceptor(config)
  6. }
  7. // 2.判断是否需要显示loading
  8. if (config.showLoading === false) {
  9. this.showLoading = config.showLoading
  10. }
  11. this.instance
  12. .request<any, T>(config)
  13. .then((res) => {
  14. // 1.单个请求对数据的处理
  15. if (config.interceptors?.responseInterceptor) {
  16. res = config.interceptors.responseInterceptor(res)
  17. }
  18. // 2.将showLoading设置true, 这样不会影响下一个请求
  19. this.showLoading = DEAFULT_LOADING
  20. // 3.将结果resolve返回出去
  21. resolve(res)
  22. })
  23. .catch((err) => {
  24. // 将showLoading设置true, 这样不会影响下一个请求
  25. this.showLoading = DEAFULT_LOADING
  26. reject(err)
  27. return err
  28. })
  29. })
  30. }
  31. get<T>(config: HYRequestConfig<T>): Promise<T> {
  32. return this.request<T>({ ...config, method: 'GET' })
  33. }
  34. post<T>(config: HYRequestConfig<T>): Promise<T> {
  35. return this.request<T>({ ...config, method: 'POST' })
  36. }
  37. delete<T>(config: HYRequestConfig<T>): Promise<T> {
  38. return this.request<T>({ ...config, method: 'DELETE' })
  39. }
  40. patch<T>(config: HYRequestConfig<T>): Promise<T> {
  41. return this.request<T>({ ...config, method: 'PATCH' })
  42. }

3.完整的index.ts文件和type.ts

  1. import axios from 'axios'
  2. import type { AxiosInstance } from 'axios'
  3. //导入自己定义的两个类型
  4. import type { HYRequestInterceptors, HYRequestConfig } from './type'
  5. import { ElLoading } from 'element-plus/lib/components/loading/index'
  6. import { LoadingInstance } from 'element-plus/lib/components/loading/src/loading'
  7. const DEAFULT_LOADING = true
  8. class ZJRequest {
  9. instance: AxiosInstance
  10. interceptors?: HYRequestInterceptors
  11. showLoading: boolean
  12. loading?: LoadingInstance
  13. constructor(config: HYRequestConfig) {
  14. this.instance = axios.create(config)
  15. this.showLoading = config.showLoading ?? true
  16. this.interceptors = config.interceptors
  17. this.instance.interceptors.request.use(
  18. this.interceptors?.requestInterceptor,
  19. this.interceptors?.requestInterceptorCatch
  20. )
  21. this.instance.interceptors.response.use(
  22. this.interceptors?.responseInterceptor,
  23. this.interceptors?.responseInterceptorCatch
  24. )
  25. // 添加所有的实例都有的拦截器
  26. this.instance.interceptors.request.use(
  27. (config) => {
  28. // console.log('所有的实例都有的拦截器:请求拦截成功')
  29. if (this.showLoading) {
  30. this.loading = ElLoading.service({
  31. lock: true,
  32. text: '正在请求数据....',
  33. background: 'rgba(0,0,0,0.5)'
  34. })
  35. }
  36. return config
  37. },
  38. (err) => {
  39. // console.log('所有的实例都有的拦截器:请求拦截失败')
  40. return err
  41. }
  42. )
  43. this.instance.interceptors.response.use(
  44. (res) => {
  45. // console.log('所有的实例都有的拦截器:响应拦截成功')
  46. // 将loading移除
  47. this.loading?.close()
  48. // 将loading移除
  49. // this.loading?.close()
  50. const data = res.data
  51. if (data.returnCode === '-1001') {
  52. console.log('请求失败,错误信息')
  53. } else {
  54. return data
  55. }
  56. },
  57. (err) => {
  58. console.log('所有的实例都有的拦截器:响应拦截失败')
  59. // 将loading移除
  60. this.loading?.close()
  61. if (err.response.status === 404) {
  62. console.log('404的错误')
  63. }
  64. return err
  65. }
  66. )
  67. }
  68. request<T>(config: HYRequestConfig<T>): Promise<T> {
  69. return new Promise((resolve, reject) => {
  70. // 1.单个请求对请求config的处理
  71. if (config.interceptors?.requestInterceptor) {
  72. config = config.interceptors.requestInterceptor(config)
  73. }
  74. // 2.判断是否需要显示loading
  75. if (config.showLoading === false) {
  76. this.showLoading = config.showLoading
  77. }
  78. this.instance
  79. .request<any, T>(config)
  80. .then((res) => {
  81. // 1.单个请求对数据的处理
  82. if (config.interceptors?.responseInterceptor) {
  83. res = config.interceptors.responseInterceptor(res)
  84. }
  85. // 2.将showLoading设置true, 这样不会影响下一个请求
  86. this.showLoading = DEAFULT_LOADING
  87. // 3.将结果resolve返回出去
  88. resolve(res)
  89. })
  90. .catch((err) => {
  91. // 将showLoading设置true, 这样不会影响下一个请求
  92. this.showLoading = DEAFULT_LOADING
  93. reject(err)
  94. return err
  95. })
  96. })
  97. }
  98. get<T>(config: HYRequestConfig<T>): Promise<T> {
  99. return this.request<T>({ ...config, method: 'GET' })
  100. }
  101. post<T>(config: HYRequestConfig<T>): Promise<T> {
  102. return this.request<T>({ ...config, method: 'POST' })
  103. }
  104. delete<T>(config: HYRequestConfig<T>): Promise<T> {
  105. return this.request<T>({ ...config, method: 'DELETE' })
  106. }
  107. patch<T>(config: HYRequestConfig<T>): Promise<T> {
  108. return this.request<T>({ ...config, method: 'PATCH' })
  109. }
  110. }
  111. export default ZJRequest
  1. import type { AxiosRequestConfig, AxiosResponse } from 'axios'
  2. export interface HYRequestInterceptors<T = AxiosResponse> {
  3. requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
  4. requestInterceptorCatch?: (error: any) => any
  5. responseInterceptor?: (res: T) => T
  6. responseInterceptorCatch?: (error: any) => any
  7. }
  8. export interface HYRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
  9. interceptors?: HYRequestInterceptors<T>
  10. showLoading?: boolean
  11. }

4.在index.js先导入ZJRequest

从config中导入相关的配置

new一个实例

  1. //service统一的出口
  2. import ZJRequest from './request'
  3. import { BASE_URL, TIME_OUT } from './request/config'
  4. import localCache from '@/utils/cache'
  5. // export default hyRequest =new HYRequest (){
  6. // }
  7. const zjRequest = new ZJRequest({
  8. baseURL: BASE_URL,
  9. timeout: TIME_OUT,
  10. // 这是拦截器
  11. interceptors: {
  12. requestInterceptor: (config) => {
  13. // 携带token的拦截
  14. const token = localCache.getCache('token')
  15. if (token) {
  16. // 注意要加这个感叹号,不然会报错
  17. config.headers!.Authorization = `Bearer ${token}`
  18. }
  19. console.log(config)
  20. // console.log('请求成功的拦截')
  21. return config
  22. },
  23. requestInterceptorCatch: (err) => {
  24. // console.log('请求失败的拦截')
  25. return err
  26. },
  27. responseInterceptor: (res) => {
  28. // console.log('响应成功的拦截')
  29. return res
  30. },
  31. responseInterceptorCatch: (err) => {
  32. // console.log('响应失败的拦截')
  33. return err
  34. }
  35. }
  36. })
  37. export default zjRequest

5.测试是否发送请求成功

先定义返回的数据类型文件type.ts

  1. export interface IDataType<T = any> {
  2. code: number
  3. data: T
  4. }

 之后对应的请求代码中,可以加入IDataType规范返回的数据类型

  1. export function requestUserInfoById(id: number) {
  2. return hyRequest.get<IDataType>({
  3. url: LoginAPI.LoginUserInfo + id,
  4. showLoading: false
  5. })
  6. }

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号