axios – npm官网:axios – npm

axios解决高并发:

axios.all() 和 axios.spread()

使用方法:

  import axios from "axios";  const req1 = () => {    return axios.get("@/api/req1");  };  const req2 = () => {    return axios.get("@/api/req2");  };  axios.all([req1, req2]).then((res) => {    console.log(res);  });

1.安装axios:
npm install axios -S

2.安装qs,qs的作用是将提交的对象进行数据类型的转换
npm install qs -S

3.在src下新建目录request,新建一个index.ts
index.ts:

import axios, { AxiosInstance, AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'import { ElMessage } from 'element-plus'// 数据返回的接口// 定义请求响应参数,不含datainterface Result {    code: number;    msg: string}// 请求响应参数,包含datainterface ResultData extends Result {    data?: T;}const URL: string = ''enum RequestEnums {    TIMEOUT = 20000,    OVERDUE = 600, // 登录失效    FAIL = 999, // 请求失败    SUCCESS = 200, // 请求成功}const config = {    // 默认地址    baseURL: URL as string,    // 设置超时时间    timeout: RequestEnums.TIMEOUT as number,    // 跨域时候允许携带凭证    withCredentials: true}class RequestHttp {    // 定义成员变量并指定类型    service: AxiosInstance;    public constructor(config: AxiosRequestConfig) {        // 实例化axios        this.service = axios.create(config);        /**         * 请求拦截器         * 客户端发送请求 -> [请求拦截器] -> 服务器         * token校验(JWT) : 接受服务器返回的token,存储到vuex/pinia/本地储存当中         */        this.service.interceptors.request.use(            (config: AxiosRequestConfig) => {                const token = localStorage.getItem('token') || '';                return {                    ...config,                    headers: {                        'x-access-token': token, // 请求头中携带token信息                    }                }            },            (error: AxiosError) => {                // 请求报错                Promise.reject(error)            }        )        /**         * 响应拦截器         * 服务器换返回信息 -> [拦截统一处理] -> 客户端JS获取到信息         */        this.service.interceptors.response.use(            (response: AxiosResponse) => {                const { data, config } = response; // 解构                if (data.code === RequestEnums.OVERDUE) {                    // 登录信息失效,应跳转到登录页面,并清空本地的token                    localStorage.setItem('token', '');                    // router.replace({                    //  path: '/login'                    // })                    return Promise.reject(data);                }                // 全局错误信息拦截(防止下载文件得时候返回数据流,没有code,直接报错)                if (data.code && data.code !== RequestEnums.SUCCESS) {                    ElMessage.error(data); // 此处也可以使用组件提示报错信息                    return Promise.reject(data)                }                return data;            },            (error: AxiosError) => {                const { response } = error;                if (response) {                    this.handleCode(response.status)                }                if (!window.navigator.onLine) {                    ElMessage.error('网络连接失败');                    // 可以跳转到错误页面,也可以不做操作                    // return router.replace({                    //  path: '/404'                    // });                }            }        )    }    handleCode(code: number): void {        switch (code) {            case 400:                ElMessage.error("请求错误(400)");                break;            case 401:                ElMessage.error("未授权,请重新登录(401)");                break;            case 403:                ElMessage.error("拒绝访问(403)");                break;            case 404:                ElMessage.error("请求出错(404)");                break;            case 408:                ElMessage.error("请求超时(408)");                break;            case 500:                ElMessage.error("服务器错误(500)");                break;            case 501:                ElMessage.error("服务未实现(501)");                break;            case 502:                ElMessage.error("网络错误(502)");                break;            case 503:                ElMessage.error("服务不可用(503)");                break;            case 504:                ElMessage.error("网络超时(504)");                break;            case 505:                ElMessage.error("HTTP版本不受支持(505)");                break;            default:                ElMessage.error(`连接出错(${code})!`);                break;        }    }    // 常用方法封装    get(url: string, params?: object): Promise<ResultData> {        return this.service.get(url, { params });    }    post(url: string, params?: object): Promise<ResultData> {        return this.service.post(url, params);    }    put(url: string, params?: object): Promise<ResultData> {        return this.service.put(url, params);    }    delete(url: string, params?: object): Promise<ResultData> {        return this.service.delete(url, { params });    }}// 导出一个实例对象export default new RequestHttp(config);

* 注意: 当我们引入axios方法的时候,比如AxiosInstance提示:
(alias) interface AxiosInstance
import AxiosInstance
“AxiosInstance” 是一种类型,在同时启用了 “preserveValueImports” 和 “isolatedModules” 时,必须使用仅类型导入进行导入。ts(1444)

解决办法:找到 tsconfig.app.json ,添加:”preserveValueImports”: false,

完整的:

{  "extends": "@vue/tsconfig/tsconfig.web.json",  "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],  "exclude": ["src/**/__tests__/*"],  "compilerOptions": {    "composite": true,    "baseUrl": ".",    "paths": {      "@/*": ["./src/*"]    },        "preserveValueImports": false,    // "isolatedModules": false,  }}

4.在request根目录下新建一个api文件夹,新建一个login.ts (后续可以自定义加多个接口管理文件)

login.ts:

import axios from '../index'import qs from 'qs'namespace Login {    // 用户登录表单    export interface LoginReqForm {        username: string;        password: string;    }    // 登录成功后返回的token    export interface LoginResData {        token: string;    }}// 用户登录export const login:any = (params: Login.LoginReqForm) => {    // 返回的数据格式可以和服务端约定    return axios.post('/api/hs/api/login', qs.stringify(params));}

* 注意: 此时我们引入 qs 插件,会报错:
无法找到模块“qs”的声明文件。“d:/…/node_modules/qs/lib/index.js”隐式拥有 “any” 类型。
尝试使用 `npm i –save-dev @types/qs` (如果存在),或者添加一个包含 `declare module ‘qs’;` 的新声明(.d.ts)文件

解决办法:
在 src 根目录新建一个types文件夹,里面新建一个 index.d.ts 文件,需要单独声明一下:

types/index.d.ts:

declare module 'qs'

5.通过 proxy 配置跨域:

vite.config.ts:

import { fileURLToPath, URL } from 'node:url'import { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue'import vueJsx from '@vitejs/plugin-vue-jsx'// https://vitejs.dev/config/export default defineConfig({  plugins: [vue(), vueJsx()],  server: {    proxy: {      '/api': {        target:"https://.../",        changeOrigin: true,        rewrite: (path) => path.replace(/^\/api/, '')      }    }  },  resolve: {    alias: {      '@': fileURLToPath(new URL('./src', import.meta.url))    }  }})

6.在页面中使用:

login.vue:

    import { reactive, ref } from 'vue'    import { login } from '@/request/api/login'    const ruleForm = reactive({        username: '',        password: ''    })    const toLogin = async (ruleForm:any) => {        const data = await login(ruleForm)        console.log(data)    }