加载中...
Axios 封装
第1节:项目介绍
第2节:项目后端准备和接口文档
第3节:知识补充:Router 4
第4节:知识补充:Pinia
第5节:vite 配置
第6节:Axios 封装
课文封面

Axios 是一个基于 promise 网络请求库,进行简单的封装可以简化API调用,实现错误统一处理、身份验证、环境切换等功能。

在项目中一般会使用 axios - 基于 Promise 的网络请求库 来进行网络请求。
将 axios 进行适当的封装,在使用上可以事半功倍。

安装axios

npm install axios

基本使用

导入 axios 后就可以直接进行网络 api 请求,不过为了方便维护,处理跨域等问题会封装后再使用。

promise用法

import axios from "axios"; // get请求 axios.get("http://192.168.1.90:4000/api/login/sms?tel=13333333333") import axios from "axios"; // get请求 axios .get("http://192.168.1.90:4000/api/login/sms?tel=13333333333") .then((res) => { // 处理成功情况 console.log(res) }) .catch(function (err) { // 处理错误情况 console.log(err) }) .finally(function () { // 总是会执行 }) // post请求 axios .post("http://192.168.1.90:4000/api/login", { tel: 13333333333, code: 1234 }) .then(res => { console.log(res.data) })

async/await用法

import axios from "axios"; async function getSms() { try { const res = await axios.get("http://192.168.1.90:4000/api/login/sms?tel=13333333333") console.log(res); } catch (err) { console.error(err); } }

视频🎞️

创建实例

// 创建axios实例 let baseURL= "" if (import.meta.env.DEV) { // 开发环境 baseURL= "http://192.168.1.90:4000" } else { // 生产环境 baseURL= "http://xxx.com" } const service = axios.create({ // 配置URL公共部分,如果要解决开发环境跨域问题这里不用配,在vite.config.json中配置 baseURL: baseURL, // 设置请求超时时间单位毫秒 timeout: 15000, // 设置请求头 headers: {'X-Custom-Header': 'foobar'} })

请求拦截器

axios 的请求拦截器,允许你在发出 HTTP 请求之前,对请求进行预处理或修改
一般可以进行:

  1. 统一处理请求头:如在请求头中添加 token 或者其他信息。
  2. 请求参数统一格式化:如对查询参数进行额外的校验或格式化。
  3. 错误处理。
service.interceptors.request.use( (config) => { // 在这里可以对所有请求进行预处理,比如往请求头中添加token const token = localStorage.getItem('authToken'); if (token) { config.headers['Authorization'] = `Bearer ${token}`; } // 如果一切正常,则必须返回config对象或者Promise.resolve(config) return config }, (error) => { // 对请求错误做些什么 // 返回Promise.reject(error),这样会触发后续的错误处理器 Promise.reject(error) }, )

响应拦截器

axios 的响应拦截器会在接收到 HTTP 响应之后、调用者实际拿到响应结果之前介入处理。
一般可以进行:

  1. 统一处理响应结果:如将后端返回的数据结构标准化,或者对某些特定的状态码进行统一处理。
  2. 错误处理:针对非成功状态码(如 401、403、500 等)进行特殊处理,如用户未登录时重定向到登录页面、显示全局错误提示等。
  3. 数据缓存策略,对于某些特定类型的请求结果进行缓存,减少不必要的重复请求。
service.interceptors.response.use( (res) => { let data = res.data if (data.code !== 0) { Toast.error(data.msg) return Promise.reject(data) } return data // (相录于返回的 res 被自动 剥掉一层,变成 data 字段) }, (error) => { if (error?.request?.status === 401 && location.pathname !== "/login") { // 当用户登录超时时,清空登录状态 const store = useUsersStore() store.user = {} // 跳转到登录页 if (error.config.url !== "/api/user/info") { sessionStorage.setItem("LOGIN_REDIRECT", location.hash.substr(1)) router.replace("/login") } } return Promise.reject(error) }, )

最终代码

import axios from "axios" import {Toast} from "@/until/toast" import {useUsersStore} from "@/store/user" import router from "@/router" axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8" // 创建axios实例 const service = axios.create({ // axios中请求配置有baseURL选项,表示请求URL公共部分 // baseURL: 'http://localhost:4001', // 超时 timeout: 15000, }) // request拦截器 service.interceptors.request.use( (config) => { // 在这里可以对所有请求进行预处理,比如往请求头中添加token const token = localStorage.getItem('authToken'); if (token) { config.headers['Authorization'] = `Bearer ${token}`; } // 如果一切正常,则必须返回config对象或者Promise.resolve(config) return config }, (error) => { // 对请求错误做些什么 // 返回Promise.reject(error),这样会触发后续的错误处理器 Promise.reject(error) }, ) // 响应拦截器 service.interceptors.response.use( (res) => { let data = res.data if (data.code !== 0) { Toast.error(data.msg) return Promise.reject(data) } return data // (相录于返回的 res 被自动 剥掉一层,变成 data 字段) }, (error) => { if (error?.request?.status === 401 && location.pathname !== "/login") { // 当用户登录超时时,清空登录状态 const store = useUsersStore() store.user = {} // 跳转到登录页 if (error.config.url !== "/api/user/info") { sessionStorage.setItem("LOGIN_REDIRECT", location.hash.substr(1)) router.replace("/login") } } return Promise.reject(error) }, ) export default service

在项目中使用

在 src 下创建 api 目录,目录下创建相应模块的 js 文件 ( login.js、user.js… ),并且创建的 api 方法以 Api 结尾,这样方便与普通方法区分。
如果需要修改 api 路径,或者参数需要统一调整就可以在这里进行处理。

// /src/api/login.js import request from "@/until/request" // 发送登录验证码 export function sendSmsApi(tel) { // 这里的url不要写全从/api开始即可,方便配置环境切换/跨域 return request.get("/api/login/sms?tel=" + tel) } // ... 其它api

直接导入需要使用的 api 方法 ( sendSmsApi ) 进行使用

// /src/views/login.vue <script setup> import {ref} from "vue" import {sendSmsApi} from "@/api/login" const tel = ref(null) // 发送验证码 function sendSmsCode() { sendSmsApi(tel.value) .then((res) => { console.log(res.msg) }) } </script>