Vue封装axios异步请求

206 阅读4分钟

封装axios异步请求 封装request.js

异步请求:XMLHttpRequest ,而axios其实就是对它的封装而已。它可以完成服务端数据请求和响应(交互)也俗称接口的调用。

官网:www.axios-http.cn/

1:下载

npm install axios
yarn add axios
pnpm install axios

2: 使用

const axios = require('axios');

get请求

// 向给定ID的用户发起请求
axios.get('/user?ID=12345')
  .then(function (response) {
    // 处理成功情况
    console.log(response);
  })
  .catch(function (error) {
    // 处理错误情况
    console.log(error);
  })
  .then(function () {
    // 总是会执行
  });
​
// 上述请求也可以按以下方式完成(可选)
axios.get('/user', {
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  })
  .then(function () {
    // 总是会执行
  });  
​
// 支持async/await用法
async function getUser() {
  try {
    const response = await axios.get('/user?ID=12345');
    console.log(response);
  } catch (error) {
    console.error(error);
  }
}

post请求

// 发起一个post请求
axios({
  method: 'post',
  url: '/user/12345',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
});

请求必须是有认识路径的问题:

// 肯定没问题
const resp = await axios.post("http://45.85.69.125/login/toLogin", loginUser)
// a能 b不能
const resp = await axios.post("/login/toLogin", loginUser)

不论你调用的get/post/delete/put等。第一个参数:都是URL。

什么是URL:统一资源定位符 (一种能够方式能够快速在电脑定位的资源(图片,文件,音频,视频。数据(文本,json,.xml)))

但是URL得组成:协议(tcp/ucp) + ip+port+资源访问路径?参数,锚点-

  • ip + port 找你你访问的资源在哪里(在那台电脑上的那个服务)

3:封装思考

// 查询视频信息
const  handleLoadData = async () => {
 const resp = await  axios.post("/video/find",{},{
    headers: {'Authorization': userStore.token}
 })
 console.log('resp', resp)
}
  • post/get请求传递header时候位置不一样。能不能像办法规避这个问题
  • 能不能自动取拼接 http://localhost:8989/api ,这样我上面代码中就直接写想对路径
  • header是信息能不能统一管理。
  • 请求错误,超时,能不能监听
  • 后端返回的状态很多,但是有一些状态是要做集中处理,比如:登录,服务器错误,404错误等等

4:完整封装代码

// 1: 导入axios异步请求组件
import axios from "axios";
// 2: 把axios请求的配置剥离成一个config/index.js的文件
import axiosConfig from "./config";
// 3: 获取路由对象--原因是:在加载的过程中先加载的pinia所以不能useRouter机制。
import router from '@/router'
// 4: elementplus消息框
import KVA from "@/utils/kva.js";
// 5: 获取登录的token信息
import { useUserStore } from '@/stores/user.js'
// 6: 然后创建一个axios的实例
const request = axios.create({ ...axiosConfig })
​
// request request请求拦截器
request.interceptors.request.use(
    function(config){
        console.log("config=====>",config)
        // 这个判断就是为了那些不需要token接口做开关处理,比如:登录,检测等
        if(!config.noToken){
             // 如果 token为空,说明没有登录。你就要去登录了
            const userStore = useUserStore()
            const isLogin = userStore.isLogin
            if(!isLogin){
                router.push("/login")
                return
            }else{
                // 90b7d374acc5476eb9beabe9373b2640
                // 这里给请求头增加参数.request--header,在服务端可以通过request的header可以获取到对应参数
                // 比如go: c.GetHeader("Authorization")
                // 比如java: request.getHeader("Authorization")
                config.headers.Authorization = userStore.getToken()
                // 挤下线使用
                // config.headers.KsdUUID = userStore.uuid
            }
        }
        return config;
    },function(error){
        // 判断请求超时
        if ( error.code === "ECONNABORTED" && error.message.indexOf("timeout") !== -1) {
            KVA.notifyError('请求超时');
            // 这里为啥不写return
        }
        return Promise.reject(error);
    }
);
​
// request response 响应拦截器
request.interceptors.response.use(async (response) => {
    // 在这里应该可以获取服务端传递过来头部信息
    // 开始续期
    if(response.headers["new-authorization"]){
        const userStore = useUserStore()
        userStore.setToken(response.headers["new-authorization"])
    }
​
​
     // 包括: 没登录,黑名单,挤下线
     if(response.data?.code === 4001 ){
        KVA.notifyError(response.data.message);
        const userStore = useUserStore()
        await userStore.logout()
        router.push('/login')
        return
    }
​
​
    // cashbin的权限拦截处理
    if(response.data?.code === 80001){
        KVA.notifyError(response.data.message);
        // 如果你想调整页面,就把下面注释打开
        //router.push("/nopermission")
        return response.data;
    }
​
    if(response.data?.code === 20000){
        return response.data;
    }
​
    const isBlob = response.headers['content-type'].includes('application/octet-stream');
​
    if (isBlob) {
        return response;
    }
​
    // 所有得服务端得错误提示,全部在这里进行处理
    if (response.data?.message) {
        KVA.notifyError(response.data.message);
    }
    // 返回接口返回的错误信息
    return Promise.reject(response.data);
​
},(err) => {
    if (err && err.response) {
        switch (err.response.status) {
            case 400:
                err.message = "请求错误";
                break;
            case 401:
                err.message = "未授权,请登录";
                break;
            case 403:
                err.message = "拒绝访问";
                break;
            case 404:
                err.message = `请求地址出错: ${err.response.config.url}`;
                break;
            case 408:
                err.message = "请求超时";
                break;
            case 500:
                err.message = "服务器内部错误";
                break;
            case 501:
                err.message = "服务未实现";
                break;
            case 502:
                err.message = "网关错误";
                break;
            case 503:
                err.message = "服务不可用";
                break;
            case 504:
                err.message = "网关超时";
                break;
            case 505:
                err.message = "HTTP版本不受支持";
                break;
            default:
        }
    }
    if (err.message) {
        KVA.notifyError(err.message);
    }
     // 判断请求超时
    if ( err.code === "ECONNABORTED" && err.message.indexOf("timeout") !== -1) {
        KVA.notifyError('服务已经离开地球表面,刷新或者重试...');
    }
    // 返回接口返回的错误信息
    return Promise.reject(err);
})
​
export default request

配置信息

export default {
    method: 'get',
    // 基础url前缀
    baseURL: import.meta.env.VITE_BASE_API,
    // 请求头信息VITE_BASE_PATH
    headers: {
      'Content-Type': 'application/json;charset=UTF-8'
    },
    // 设置超时时间
    timeout: 30000,
    // 返回数据类型
    responseType: 'json'
}