element中封装axios如何实现哀求函数自界说loading

打印 上一主题 下一主题

主题 1035|帖子 1035|积分 3105

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我们的目的是想实现一个基于axios封装的函数,可以传入一个参数loading,当参数为true时,表现加载动画。不传时则不表现loading。
我们来实现
第一个版本:

首先我们写一个简朴的node服务:

  1. import  express from 'express';
  2. import cors from "cors"
  3. const app=new express()
  4. app.use(cors())
  5. app.use(express.static("public"))
  6. app.use(express.json());
  7. app.use(express.urlencoded({ extended: true }));
  8. app.post('/api/error',(req,res)=>{
  9.     console.log("accpet_beab--req---",req.url)
  10.     console.log("accpet_beab--req--data-",req.body)
  11.     res.send({
  12.         message:"ok"
  13.     })
  14. })
  15. app.get("/api/list",(req,res)=>{
  16.     console.log("query",req.query)
  17.     setTimeout(()=>{
  18.         res.json({ message: 'Protected route', data:[
  19.             {id:"11",name:"aaa"},
  20.             {id:"22",name:"bbb"},
  21.             {id:"33",name:"ccc"},
  22.         ] });
  23.     },4000)
  24. })
  25. app.post("/api/marks",(req,res)=>{
  26.     console.log("query",req.query)
  27.     setTimeout(()=>{
  28.         res.json({ message: 'Protected route', data:[
  29.             {id:"11",method:"post"},
  30.             {id:"22",method:"post"},
  31.             {id:"33",method:"post"},
  32.         ] });
  33.     },4000)
  34. })
  35. app.get("/api/log",(req,res)=>{
  36.    
  37.     res.send({
  38.         msg:"log",
  39.         data:{
  40.             name:"asage",
  41.             age:30
  42.         },
  43.         status:"ok"
  44.     })      
  45. })
  46. app.listen(4200,()=>{
  47.     console.log("服务启动成功")
  48. })
复制代码
基于axios的封装

  1. import axios, { InternalAxiosRequestConfig, AxiosResponse } from 'axios'
  2. import { ElLoading, ElMessage } from 'element-plus'
  3. import type { IResponseData, ExAxiosRequestConfig } from '@/types/core/axios'
  4. import { ENV_DEV, TIMEOUT_TIME } from '@/config/project'
  5. import { checkReturnStatus } from './fun'
  6. import { userStore } from '@/stores/user'
  7. import router from '@/router'
  8. let loadingInstance: any = null
  9. export const service = axios.create({
  10.   baseURL: MODE === ENV_DEV ? '' : VITE_BASE_URL, //这里也可以使用变量
  11.   timeout: TIMEOUT_TIME, //超时设置
  12.   //withCredentials: true, //异步请求携带cookie
  13.   headers: {
  14.   }
  15. })
  16. //request interceptor  请求拦截器
  17. service.interceptors.request.use(
  18.   (config: InternalAxiosRequestConfig) => {
  19.     const { token } = userStore()
  20.     //针对post/put等请求处理
  21.     if (config?.data?.showLoading) {
  22.       loadingInstance = ElLoading.service({
  23.         fullscreen: true,
  24.         text: '正在加载',
  25.         spinner: 'el-icon-loading',
  26.         background: 'rgba(0, 0, 0, 0.3)'
  27.       })
  28.     }
  29.     //针对get/delete等请求处理
  30.     if (config?.params?.showLoading) {
  31.       loadingInstance = ElLoading.service({
  32.         fullscreen: true,
  33.         text: '正在加载',
  34.         spinner: 'el-icon-loading',
  35.         background: 'rgba(0, 0, 0, 0.3)'
  36.       })
  37.     }
  38.     config.headers.token = `${token || ''}`
  39.     return config
  40.   },
  41.   (error) => {
  42.     console.log('request--error', error)
  43.     return Promise.reject(error)
  44.   }
  45. )
  46. //响应拦截器
  47. service.interceptors.response.use(
  48.   (response: AxiosResponse): AxiosResponse<IResponseData> => {
  49.    
  50.     if (loadingInstance) {
  51.       loadingInstance.close()
  52.     }
  53.     if (response.status !== 200) {
  54.       
  55.       const err = {
  56.         data: {},
  57.         errcode: -99999,
  58.         errmsg: '请求失败!'
  59.       }
  60.       // Promise.reject(err);
  61.       throw err
  62.     }
  63.     if (response.headers.token) setToken(response.headers.token)
  64.     const res = response.data
  65.    
  66.     const status = checkReturnStatus(res.errcode)
  67.     switch (status) {
  68.       case -1:
  69.         ElMessage.error('登录信息已发生改变,请重新登录!')
  70.         throw res
  71.       case 0:
  72.         ElMessage.error('系统繁忙,请稍后再试!')
  73.         throw res
  74.       case 1:
  75.         console.log('case----1-', res)
  76.         return res
  77.       case -2:
  78.         ElMessage.error(res.errmsg)
  79.         throw res
  80.       case 70003:
  81.         ElMessage({
  82.           message: res.errmsg,
  83.           type: 'error',
  84.           duration: 1500
  85.         })
  86.         throw res
  87.     }
  88.   },
  89.   (error) => {
  90.     // 在响应错误的时候的逻辑处理
  91.     if (error.code === 'ECONNABORTED' || error.message === 'Network Error' || error.message.includes('timeout')) {
  92.       ElMessage({ type: 'error', message: '当前网络错误' })
  93.     }
  94.     return Promise.reject(error)
  95.   }
  96. )
  97. // class HTTP {
  98. export const http = {
  99.   get(url: string, config: InternalAxiosRequestConfig & any = {}, showLoading = false) {
  100.     config = { ...config.params, showLoading }
  101.     return new Promise((resolve, reject) => {
  102.       service
  103.         .get(url, config)
  104.         .then((res) => {
  105.           resolve(res)
  106.         })
  107.         .catch((err) => {
  108.           reject(err)
  109.         })
  110.     })
  111.   },
  112.   post(url: string, config: InternalAxiosRequestConfig & any = {}, showLoading = false) {
  113.     return new Promise((resolve, reject) => {
  114.       config = { ...config, showLoading }
  115.       service
  116.         .post(url, config)
  117.         .then((res) => {
  118.           resolve(res)
  119.         })
  120.         .catch((err) => {
  121.           reject(err)
  122.         })
  123.     })
  124.   },
  125.   delete(url: string, config: InternalAxiosRequestConfig & any = {}, showLoading = false) {
  126.     config = { ...config.params, showLoading }
  127.     return new Promise((resolve, reject) => {
  128.       service
  129.         .delete(url, config)
  130.         .then((res) => {
  131.           resolve(res)
  132.         })
  133.         .catch((err) => {
  134.           reject(err)
  135.         })
  136.     })
  137.   },
  138.   put(url: string, config: InternalAxiosRequestConfig & any = {}, showLoading = false) {
  139.     return new Promise((resolve, reject) => {
  140.       config = { ...config, showLoading }
  141.       service
  142.         .put(url, config)
  143.         .then((res) => {
  144.           resolve(res)
  145.         })
  146.         .catch((err) => {
  147.           reject(err)
  148.         })
  149.     })
  150.   }
  151. }
复制代码
再看一看详细的http哀求

  1. export function getAllRolesData(params): Promise<IResponseData> {
  2.   return http.post('/api/permission/getAllMenu', params, false)
  3. }
复制代码
以上根本上就可以实现了我们的自界说loading结果。我们传入的第三个参数可以自主的控制当前哀求是否需要实现loading。
但是这里有一个标题:就是我们的全部哀求。都会在参数列表中带上了一个loading的无用参数。
那我们是否有办法实现我们的业务哀求中依然带上这个参数loading,但是我们真实的http哀求中
却没有出现呢?
答案是有的。这里我们要针对post/get哀求单独做处理。改进后的代码
第二版

  1. import axios from 'axios';
  2. import { ElLoading } from 'element-plus';
  3. // 创建 axios 实例
  4. const service = axios.create({
  5.   baseURL: '', // 根据你的需要设置基础URL
  6.   timeout: 5000 // 请求超时时间
  7. });
  8. // 请求拦截器
  9. service.interceptors.request.use(
  10.   config => {
  11.     // 在这里可以进行一些请求前的操作,例如添加token等
  12.     return config;
  13.   },
  14.   error => {
  15.     // 请求错误时的操作
  16.     return Promise.reject(error);
  17.   }
  18. );
  19. // 响应拦截器
  20. service.interceptors.response.use(
  21.   response => {
  22.     // 请求成功后的操作
  23.     return response;
  24.   },
  25.   error => {
  26.     // 响应错误时的操作
  27.     return Promise.reject(error);
  28.   }
  29. );
  30. // 请求转换函数,用于移除请求配置中的 loading 参数
  31. service.defaults.transformRequest = [
  32.   function (data) {
  33.     debugger
  34.     // 检查 data 是否是对象,并且有 loading 属性
  35.     if (data && typeof data === 'object' && 'loading' in data) {
  36.       // 移除 data 中的 loading 属性
  37.       const { loading, ...configWithoutLoading } = data;
  38.     //   debugger
  39.       return configWithoutLoading;
  40.     }
  41.     // 如果 data 不是对象或者没有 loading 属性,则直接返回
  42.     return data;
  43.   }
  44. ];
  45. // 封装请求函数
  46. function request(config) {
  47.   // 处理 loading 动画
  48.   let loadingInstance = null;
  49.   if (config.loading) {
  50.     loadingInstance = ElLoading.service({ fullscreen: true });
  51.   }
  52.   //针对get进行处理
  53.   if (config.method === 'get' && config.params) {
  54.     // 对 params 做一些额外处理
  55.     const { loading, ...paramsWithoutLoading } = config.params || {};
  56.     config.params = paramsWithoutLoading;
  57.     // debugger
  58.   }
  59.   // 发送请求
  60.   return service(config).finally(() => {
  61.     // 请求完成后关闭加载动画(如果存在)
  62.     if (loadingInstance) {
  63.       loadingInstance.close();
  64.     }
  65.   });
  66. }
  67. // 导出封装后的请求函数
  68. export default request;
复制代码
在详细页面中进行使用:

  1. import {request} from "../utils/http2"
  2. request(
  3.   "/api/list",
  4.   'get',
  5.   {
  6.     pageNo:1,
  7.     pageSize:10
  8.   },
  9.   true
  10. ).then(res=>{
  11.     console.log("list---res",res)
  12. }).catch(err=>{
  13.     console.log("err",err)
  14. })
复制代码
这里的核心就是单独针对post和get哀求做处理。针对post,我们通过transformRequest对post哀求中的data进行改造,去掉loading参数。而针对get哀求,则通过config.params去掉loading。如许就可以实现自主可控的loading
提醒:这里有个地方要特别留意。
  1. // 请求转换函数,用于移除请求配置中的 loading 参数
  2. service.defaults.transformRequest = [
  3.   function (data) {
  4.     debugger
  5.     // 检查 data 是否是对象,并且有 loading 属性
  6.     if (data && typeof data === 'object' && 'loading' in data) {
  7.       // 移除 data 中的 loading 属性
  8.       const { loading, ...configWithoutLoading } = data;
  9.     //   debugger
  10.       return configWithoutLoading;
  11.     }
  12.     // 如果 data 不是对象或者没有 loading 属性,则直接返回
  13.     return data;
  14.   }
  15. ];
复制代码
这里假如我们在真实的http哀求中发现对于post/put哀求的request payload是[object,object],是因为我们没有把post哀求参数序列化。所以我们要做一点修正
  1. //针对post/put请求处理loading参数问题
  2. service.defaults.transformRequest = [
  3.   function (data) {
  4.     if (data && typeof data === 'object' && 'loading' in data) {
  5.       // 移除 data 中的 loading 属性
  6.       const configWithoutLoading = JSON.parse(JSON.stringify(data))
  7.       delete configWithoutLoading.loading
  8.       return JSON.stringify(configWithoutLoading)
  9.     }
  10.     // 如果 data 不是对象或者没有 loading 属性,则直接返回
  11.     return JSON.stringify(data)
  12.   }
  13. ]
复制代码
如许就正常得到参数了

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户云卷云舒

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表