axios不入门直接起飞

Axios

Axios是什么?

Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests

1.安装

使用npm安装:

npm install axios

使用yarn安装:

yarn add axios

2.包装统一请求工具

因为后端地址是一样的,假设是localhost:8080,只是请求路径不一样,我们可以定义一个baseURL,此处使用/api是为了解决跨域问题

1.先包装一个工具request.js

import axios from "axios";

const baseURL = "/api";
const instance = axios.create({baseURL});
export default instance;

2.在vite.config.js文件中添加配置,将/api删除,替换为http://localhost:8080,这样就相当于使用前端服务发送请求而不是浏览器,解决了跨域请求问题

export default defineConfig({
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
//代理http请求,解决跨域问题
server: {
host: 'localhost',
port: 5173,
proxy: {
'/api': { //匹配请求路径中含有 /api 的请求
target: 'http://localhost:8080', //后端服务地址
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '') //去除路径中的/api,还原请求路径
}
}
},
})

3.拦截器

这是axios发送请求的一个示例,项目中会有很多这样的请求要发送,我们会发现发送请求和接收响应数据之前,我们都会做一些相同的事情,比如,发送请求之前我们都会给请求头中带上token接收响应时我们都会先判断状态码,我们不妨将这些动作用一个统一的函数来实现,这就需要使用拦截器

axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});

这是一个响应拦截器的示例,axios会自动适配响应的http状态码为4xx或5xx的请求为失败回调,在失败回调中我们可以对各种状态码的失败回调统一处理,成功回调中如果自定义的code为0也表示有错误,这种统一处理的方式类似于Spring中的AOP

//响应拦截器,状态码为2xx时执行成功回调,否则执行失败回调
instance.interceptors.response.use(
//成功回调
(result) => {
// 如果状态码为0,后端发生异常
if (result.data.code = 0) {
ElMessage.error(result.data.msg);
return Promise.reject(result);
}
return result.data;
},
//失败回调
(error) => {
// 状态码为401,419都跳转到登录界面
if (error.response) {
const code = error.response.status;
if (code = 401) {
ElMessage({message: '请先登录!', type: "error",});
router.push('/login');
} else if (code = 419) {
ElMessage.error("身份已过期,请重新登录!");
router.push('/login');
} else {
ElMessage.error("服务器异常!" + code);
}
}
// 将异步的状态设置为失败状态
return Promise.reject(error);
}
);

这是一个请求拦截器的示例,在发送请求之前先判断是否有token,如果有就在请求头上带上token再发送请求,否则跳转到登录页面,当然,登录和注册请求都不需要token,可以直接发送请求

// 请求拦截器
instance.interceptors.request.use(
(config) => {
//登录请求不需要token
if (config.url.endsWith('/login') || config.url.endsWith('/register')) {
return config;
}
//如果有token,将token放入请求头中
const token = tokenStore.token;
if (token != null) {
config.headers['token'] = token;
} else {
router.push('/login');
ElMessage({message: '请先登录!', type: "error",});
return Promise.reject('token不存在!');
}
return config;
},
(err) => {
//请求错误的回调
return Promise.reject(err);
}
);

4.完整axios包装工具示例

import axios from "axios";
import {ElMessage} from "element-plus";
import router from "@/router";
import {useTokenStore} from "@/stores/token.js";

const baseURL = "/api";
const instance = axios.create({baseURL});
const tokenStore = useTokenStore();


//响应拦截器,状态码为2xx时执行成功回调,否则执行失败回调
instance.interceptors.response.use(
//成功回调
(result) => {
// 如果状态码为0,后端发生异常
if (result.data.code = 0) {
ElMessage.error(result.data.msg);
return Promise.reject(result);
}
return result.data;
},
//失败回调
(error) => {
// 状态码为401,419都跳转到登录界面
if (error.response) {
const code = error.response.status;
if (code = 401) {
ElMessage({message: '请先登录!', type: "error",});
router.push('/login');
} else if (code = 419) {
ElMessage.error("身份已过期,请重新登录!");
router.push('/login');
} else {
ElMessage.error("服务器异常!" + code);
}
}
// 将异步的状态设置为失败状态
return Promise.reject(error);
}
);

// 请求拦截器
instance.interceptors.request.use(
(config) => {
//登录请求不需要token
if (config.url.endsWith('/login') || config.url.endsWith('/register')) {
return config;
}
//如果有token,将token放入请求头中
const token = tokenStore.token;
if (token != null) {
config.headers['token'] = token;
} else {
router.push('/login');
ElMessage({message: '请先登录!', type: "error",});
return Promise.reject('token不存在!');
}
return config;
},
(err) => {
//请求错误的回调
return Promise.reject(err);
}
);

export default instance;

在其他接口文件中导入使用,因为使用的是export default instance默认导出的,所以导入时可以自定义名字,这个文件中定义为request,其实就是instance实例

import request from "@/util/request.js";
// 用户退出登录
const logoutService = function () {
// 调用后端接口清除redis中的令牌
return request.delete('/logout');
}

export {logoutService}