个人博客——axios封装

封装axios,使代码更简洁,也便于对请求和响应进行统一管理。

封装常用请求方法

定义axios的配置信息,用于在创建axios实例时传入,封装常用的get、put、post、delete接口方法。

  1. 在src\router\index.ts写入以下代码

import axios, {AxiosInstance,AxiosRequestConfig} from 'axios'
// 数据返回的接口
// 定义请求响应参数
interface Result<T> {
  code: number;
  msg: string;
  data?: T;
}

const config = {
  // 默认地址
  baseURL: "http://localhost:8080",
  // 设置超时时间
  timeout: 3000,
}

class Request {
  // 定义成员变量并指定类型
  service: AxiosInstance;
  public constructor(config: AxiosRequestConfig) {
    // 实例化axios
    this.service = axios.create(config);


  }

  // 常用方法封装
  get<T>(url: string, params?: object): Promise<Result<T>> {
    return this.service.get(url, {params});
  }
  post<T>(url: string, params?: object): Promise<Result<T>> {
    return this.service.post(url, params);
  }
  put<T>(url: string, params?: object): Promise<Result<T>> {
    return this.service.put(url, params);
  }
  delete<T>(url: string, params?: object): Promise<Result<T>> {
    return this.service.delete(url, {params});
  }
}

// 导出一个实例对象
export default new Request(config);
  1. 封装完毕后使用在src\api\loginRegister.ts,中使用封装好的方法
import request from '../utils/request'

export default {
    test:()=>{
        return request.get('user/getMessage');
    },
}
  1. 在页面中使用src\api\loginRegister.ts中的方法
<template>
    
    <div> 
        <el-button type="primary" size="default" @click="test">test</el-button>
    </div>
</template>

<script setup lang="ts">
import lAndR from "../../api/loginRegister"
const test = ()=>{
    lAndR.test().then((res)=>{
        console.log("test",res);
        
    })
}

</script>

<style lang="scss" scoped>

</style>

至此,axios常用方法的封装完成了。

请求拦截器

用于在发送请求前给请求头添加token

//请求拦截器
    this.service.interceptors.request.use(
     //这里的config声明为AxiosRequestConfig类型会报错,很奇怪
       (config: any) => {
    //将token从userStore取出放入请求头中
        const token = userMsg.userToken || '';
       config.headers.token = token;
         return config;
       },
       (error: any) => {
         // 请求报错
         Promise.reject(error)
       }
     )

未添加token的请求头
在这里插入图片描述
添加token后的请求头
在这里插入图片描述

响应拦截器

响应拦截器,对token过期或失效进行处理;拦截全局错误信息

/**
 * 响应拦截器
 */
this.service.interceptors.response.use(
  (response: AxiosResponse) => {
   const {data} = response; // 解构
   if (data.code === 3010) {
    // 3010登录信息失效码,清空token
    userMsg.setToken('');
   return Promise.reject(data);
   }
   // 全局错误信息拦截(防止下载文件得时候返回数据流,没有code,直接报错)
   if (data.code && data.code !== 2000) {
    ElMessage.error(data); 
    return Promise.reject(data)
   }
   //页面请求的返回结果
   return data;
  },
  (error: AxiosError) => {
   const {response} = error;
   if (response) {
    ElMessage.error('请求失败');
   }
   if (!window.navigator.onLine) {
    ElMessage.error('网络连接失败');
    });
   }
  }
)

需要注意是,添加响应拦截器后,在页面中请求的返回结果,是拦截器中解构后返回的data,因此数据的结构和之前的有所不同,比如res.data.data.role变成res.data.role。
同时因为因为对状态码的处理都在响应拦截器进行,所以在页面中请求时不需要额外对状态码进行判断处理,直接在then和catch中写请求成功或失败后的处理即可
例如,未添加响应拦截器前的登录请求

const toLogin = async() => {
  //进行表单校验,返回promise
 await formRef.value?.validate().then(()=>{
  let user={
    userName:form.name,
    passward:form.password
   }  
  lAndR.login(user).then((res)=>{
    if(res.data.code === 2000){
      userMsg.setToken(res.data.data.token);
      ElMessage.success("登录成功");
      router.replace("/");
    }else{
        ElMessage.error(res.data.msg);
        clear();
    }
    console.log(res);
    
   })
 })
 .catch((err)=>{
  console.log(err[0]); 
  ElMessage.error('校验失败');
    
  })

}

添加响应拦截器后的登录请求

const toLogin = async() => {
  //进行表单校验,返回promise
 await formRef.value?.validate().then(()=>{
  let user={
    userName:form.name,
    passward:form.password
   } 
   
   console.log("user",user);
  lAndR.login(user).then((res:any)=>{
      userMsg.setToken(res.data.token);
      ElMessage.success("登录成功");
      if(res.data.role == 1){       
        router.replace("/BackendHome");
      }else{
        router.replace("/");
      }     
     console.log(res);    
   }).catch(()=>{
      clear();
   })
 })
 .catch(()=>{
  ElMessage.error('校验失败');   
  })

}

封装axios请求和设置拦截器参考文章

至此axios常用请求封装和请求响应拦截器的设置就完成辣,完整代码如下


import axios, {AxiosInstance,AxiosRequestConfig,AxiosResponse,AxiosError} from 'axios'
import {userStore} from '../stores'
import { useRouter } from "vue-router";
import { ElMessage } from 'element-plus'

const userMsg = userStore();
const router = useRouter();

// 数据返回的接口
// 定义请求响应参数
interface Result<T> {
  code: number;
  msg: string;
  data?: T;
}

const config = {
  // 默认地址
  baseURL: "http://localhost:8080",
  // 设置超时时间
  timeout: 3000,
  // 跨域时候允许携带凭证
//   withCredentials: true
}

class Request {
  // 定义成员变量并指定类型
  service: AxiosInstance;
  public constructor(config: AxiosRequestConfig) {
   // 实例化axios
   this.service = axios.create(config);

    /**请求拦截器
     * 发起请求时添加token
    */
   this.service.interceptors.request.use(
     //这里的config声明为AxiosRequestConfig类型会报错,很奇怪
     (config: any) => {
    //将token从userStore取出放入请求头中
     const token = userMsg.userToken || '';
       config.headers.token = token;
      return config;
     },
     (error: AxiosError) => {
      // 请求报错
      Promise.reject(error)
     }
    )
     
    /**
     * 响应拦截器
     * 1.对token过期或失效进行处理
     * 2.拦截全局错误信息
     */
    this.service.interceptors.response.use(
      (response: AxiosResponse) => {
       const {data} = response; // 解构
       if (data.code === 3010) {
        // 3010登录信息失效码,应跳转到登录页面,并清空token
        userMsg.setToken('');
       return Promise.reject(data);
       }
       // 全局错误信息拦截(防止下载文件得时候返回数据流,没有code,直接报错)
       if (data.code && data.code !== 2000) {
        console.log(data.code !== 2000)
        ElMessage.error(data.msg); 
        return Promise.reject(data)
       }  
       return data;
      },
      (error: AxiosError) => {
       const {response} = error;
       if (response) {
        ElMessage.error('请求失败');
       }
       if (!window.navigator.onLine) {
        ElMessage.error('网络连接失败');
        });
       }
      }
    )

  }


  // 常用方法封装
  get<T>(url: string, params?: object): Promise<Result<T>> {
    return this.service.get(url, {params});
  }
  post<T>(url: string, params?: object): Promise<Result<T>> {
    return this.service.post(url, params);
  }
  put<T>(url: string, params?: object): Promise<Result<T>> {
    return this.service.put(url, params);
  }
  delete<T>(url: string, params?: object): Promise<Result<T>> {
    return this.service.delete(url, {params});
  }
}

// 导出一个实例对象
export default new Request(config);



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值