马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
我们的目的是想实现一个基于axios封装的函数,可以传入一个参数loading,当参数为true时,表现加载动画。不传时则不表现loading。
我们来实现
第一个版本:
首先我们写一个简朴的node服务:
- import express from 'express';
- import cors from "cors"
- const app=new express()
- app.use(cors())
- app.use(express.static("public"))
- app.use(express.json());
- app.use(express.urlencoded({ extended: true }));
- app.post('/api/error',(req,res)=>{
- console.log("accpet_beab--req---",req.url)
- console.log("accpet_beab--req--data-",req.body)
- res.send({
- message:"ok"
- })
- })
- app.get("/api/list",(req,res)=>{
- console.log("query",req.query)
- setTimeout(()=>{
- res.json({ message: 'Protected route', data:[
- {id:"11",name:"aaa"},
- {id:"22",name:"bbb"},
- {id:"33",name:"ccc"},
- ] });
- },4000)
- })
- app.post("/api/marks",(req,res)=>{
- console.log("query",req.query)
- setTimeout(()=>{
- res.json({ message: 'Protected route', data:[
- {id:"11",method:"post"},
- {id:"22",method:"post"},
- {id:"33",method:"post"},
- ] });
- },4000)
- })
- app.get("/api/log",(req,res)=>{
-
- res.send({
- msg:"log",
- data:{
- name:"asage",
- age:30
- },
- status:"ok"
- })
- })
- app.listen(4200,()=>{
- console.log("服务启动成功")
- })
复制代码 基于axios的封装
- import axios, { InternalAxiosRequestConfig, AxiosResponse } from 'axios'
- import { ElLoading, ElMessage } from 'element-plus'
- import type { IResponseData, ExAxiosRequestConfig } from '@/types/core/axios'
- import { ENV_DEV, TIMEOUT_TIME } from '@/config/project'
- import { checkReturnStatus } from './fun'
- import { userStore } from '@/stores/user'
- import router from '@/router'
- let loadingInstance: any = null
- export const service = axios.create({
- baseURL: MODE === ENV_DEV ? '' : VITE_BASE_URL, //这里也可以使用变量
- timeout: TIMEOUT_TIME, //超时设置
- //withCredentials: true, //异步请求携带cookie
- headers: {
- }
- })
- //request interceptor 请求拦截器
- service.interceptors.request.use(
- (config: InternalAxiosRequestConfig) => {
- const { token } = userStore()
- //针对post/put等请求处理
- if (config?.data?.showLoading) {
- loadingInstance = ElLoading.service({
- fullscreen: true,
- text: '正在加载',
- spinner: 'el-icon-loading',
- background: 'rgba(0, 0, 0, 0.3)'
- })
- }
- //针对get/delete等请求处理
- if (config?.params?.showLoading) {
- loadingInstance = ElLoading.service({
- fullscreen: true,
- text: '正在加载',
- spinner: 'el-icon-loading',
- background: 'rgba(0, 0, 0, 0.3)'
- })
- }
- config.headers.token = `${token || ''}`
- return config
- },
- (error) => {
- console.log('request--error', error)
- return Promise.reject(error)
- }
- )
- //响应拦截器
- service.interceptors.response.use(
- (response: AxiosResponse): AxiosResponse<IResponseData> => {
-
- if (loadingInstance) {
- loadingInstance.close()
- }
- if (response.status !== 200) {
-
- const err = {
- data: {},
- errcode: -99999,
- errmsg: '请求失败!'
- }
- // Promise.reject(err);
- throw err
- }
- if (response.headers.token) setToken(response.headers.token)
- const res = response.data
-
- const status = checkReturnStatus(res.errcode)
- switch (status) {
- case -1:
- ElMessage.error('登录信息已发生改变,请重新登录!')
- throw res
- case 0:
- ElMessage.error('系统繁忙,请稍后再试!')
- throw res
- case 1:
- console.log('case----1-', res)
- return res
- case -2:
- ElMessage.error(res.errmsg)
- throw res
- case 70003:
- ElMessage({
- message: res.errmsg,
- type: 'error',
- duration: 1500
- })
- throw res
- }
- },
- (error) => {
- // 在响应错误的时候的逻辑处理
- if (error.code === 'ECONNABORTED' || error.message === 'Network Error' || error.message.includes('timeout')) {
- ElMessage({ type: 'error', message: '当前网络错误' })
- }
- return Promise.reject(error)
- }
- )
- // class HTTP {
- export const http = {
- get(url: string, config: InternalAxiosRequestConfig & any = {}, showLoading = false) {
- config = { ...config.params, showLoading }
- return new Promise((resolve, reject) => {
- service
- .get(url, config)
- .then((res) => {
- resolve(res)
- })
- .catch((err) => {
- reject(err)
- })
- })
- },
- post(url: string, config: InternalAxiosRequestConfig & any = {}, showLoading = false) {
- return new Promise((resolve, reject) => {
- config = { ...config, showLoading }
- service
- .post(url, config)
- .then((res) => {
- resolve(res)
- })
- .catch((err) => {
- reject(err)
- })
- })
- },
- delete(url: string, config: InternalAxiosRequestConfig & any = {}, showLoading = false) {
- config = { ...config.params, showLoading }
- return new Promise((resolve, reject) => {
- service
- .delete(url, config)
- .then((res) => {
- resolve(res)
- })
- .catch((err) => {
- reject(err)
- })
- })
- },
- put(url: string, config: InternalAxiosRequestConfig & any = {}, showLoading = false) {
- return new Promise((resolve, reject) => {
- config = { ...config, showLoading }
- service
- .put(url, config)
- .then((res) => {
- resolve(res)
- })
- .catch((err) => {
- reject(err)
- })
- })
- }
- }
复制代码 再看一看详细的http哀求
- export function getAllRolesData(params): Promise<IResponseData> {
- return http.post('/api/permission/getAllMenu', params, false)
- }
复制代码 以上根本上就可以实现了我们的自界说loading结果。我们传入的第三个参数可以自主的控制当前哀求是否需要实现loading。
但是这里有一个标题:就是我们的全部哀求。都会在参数列表中带上了一个loading的无用参数。
那我们是否有办法实现我们的业务哀求中依然带上这个参数loading,但是我们真实的http哀求中
却没有出现呢?
答案是有的。这里我们要针对post/get哀求单独做处理。改进后的代码
第二版
- import axios from 'axios';
- import { ElLoading } from 'element-plus';
- // 创建 axios 实例
- const service = axios.create({
- baseURL: '', // 根据你的需要设置基础URL
- timeout: 5000 // 请求超时时间
- });
- // 请求拦截器
- service.interceptors.request.use(
- config => {
- // 在这里可以进行一些请求前的操作,例如添加token等
- return config;
- },
- error => {
- // 请求错误时的操作
- return Promise.reject(error);
- }
- );
- // 响应拦截器
- service.interceptors.response.use(
- response => {
- // 请求成功后的操作
- return response;
- },
- error => {
- // 响应错误时的操作
- return Promise.reject(error);
- }
- );
- // 请求转换函数,用于移除请求配置中的 loading 参数
- service.defaults.transformRequest = [
- function (data) {
- debugger
- // 检查 data 是否是对象,并且有 loading 属性
- if (data && typeof data === 'object' && 'loading' in data) {
- // 移除 data 中的 loading 属性
- const { loading, ...configWithoutLoading } = data;
- // debugger
- return configWithoutLoading;
- }
- // 如果 data 不是对象或者没有 loading 属性,则直接返回
- return data;
- }
- ];
- // 封装请求函数
- function request(config) {
- // 处理 loading 动画
- let loadingInstance = null;
- if (config.loading) {
- loadingInstance = ElLoading.service({ fullscreen: true });
- }
- //针对get进行处理
- if (config.method === 'get' && config.params) {
- // 对 params 做一些额外处理
- const { loading, ...paramsWithoutLoading } = config.params || {};
- config.params = paramsWithoutLoading;
- // debugger
- }
- // 发送请求
- return service(config).finally(() => {
- // 请求完成后关闭加载动画(如果存在)
- if (loadingInstance) {
- loadingInstance.close();
- }
- });
- }
- // 导出封装后的请求函数
- export default request;
复制代码 在详细页面中进行使用:
- import {request} from "../utils/http2"
- request(
- "/api/list",
- 'get',
- {
- pageNo:1,
- pageSize:10
- },
- true
- ).then(res=>{
- console.log("list---res",res)
- }).catch(err=>{
- console.log("err",err)
- })
复制代码 这里的核心就是单独针对post和get哀求做处理。针对post,我们通过transformRequest对post哀求中的data进行改造,去掉loading参数。而针对get哀求,则通过config.params去掉loading。如许就可以实现自主可控的loading
提醒:这里有个地方要特别留意。
- // 请求转换函数,用于移除请求配置中的 loading 参数
- service.defaults.transformRequest = [
- function (data) {
- debugger
- // 检查 data 是否是对象,并且有 loading 属性
- if (data && typeof data === 'object' && 'loading' in data) {
- // 移除 data 中的 loading 属性
- const { loading, ...configWithoutLoading } = data;
- // debugger
- return configWithoutLoading;
- }
- // 如果 data 不是对象或者没有 loading 属性,则直接返回
- return data;
- }
- ];
复制代码 这里假如我们在真实的http哀求中发现对于post/put哀求的request payload是[object,object],是因为我们没有把post哀求参数序列化。所以我们要做一点修正
- //针对post/put请求处理loading参数问题
- service.defaults.transformRequest = [
- function (data) {
- if (data && typeof data === 'object' && 'loading' in data) {
- // 移除 data 中的 loading 属性
- const configWithoutLoading = JSON.parse(JSON.stringify(data))
- delete configWithoutLoading.loading
- return JSON.stringify(configWithoutLoading)
- }
- // 如果 data 不是对象或者没有 loading 属性,则直接返回
- return JSON.stringify(data)
- }
- ]
复制代码 如许就正常得到参数了
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |