【Vue3速成】07-vue3异步请求之Axios-01

🎯 你正在阅读「半路出家玩前端」系列文章 🎯

🔥 弹简特 个人主页

❄️ 个人专栏直通车:

靠热爱去书写自己,靠勇敢去书写生活!


🌟 博主简介:


文章目录:


一、前言

铁汁么,我们前端终归是要和后端交互的,那么在和后端交互的时候,我们需要请求后端,那么到底是同步请求还是异步请求,我们本期就将他梳理清楚。

二、案例演示

1、项目结构

2、根组件代码

html 复制代码
<!--
  土味情话页面:
  1) onMounted / 按钮 → 调用 getLoveMessage
  2) Axios 请求后端 http://localhost:8080/api/情话
  3) 取 response.data,用 Object.assign 写入 reactive,模板回显
  前置:后端已启动,并配置 @CrossOrigin 允许跨域
-->
<script setup>
import { reactive, onMounted } from 'vue'
import axios from 'axios'

/**
 * 页面模型(响应式对象)
 * 先给默认字段;请求成功后用 Object.assign 覆盖属性值
 * 注意:不要整对象替换(jsonData = xxx),否则响应式可能失效
 */
const jsonData = reactive({
  code: 0,
  content: '加载中...',
})

/**
 * 向后端拉取一句土味情话
 * - async:本函数返回 Promise
 * - await:等 Axios 结果回来再往下执行(否则打印/赋值会抢跑)
 */
async function getLoveMessage() {
  try {
    // axios(...) 返回 Promise;成功时拿到完整响应对象 response
    const response = await axios({
      method: 'get', // 查询用 get
      // 与后端 Controller 映射路径保持一致
      url: 'http://localhost:8080/api/情话',
      // params: { username: 'admin' }, // GET 查询参数(拼到 URL)
      // data: { ... },                // 请求体(POST 常用)
    })

    // response:Axios 包装的响应(含 status、headers、data...)
    // response.data:后端返回的业务 JSON,例如 { code, content }
    // 若后端还有统一 Result 包装,可能是 response.data.data
    console.log('完整响应对象:', response)
    console.log('业务 JSON:', response.data)

    // 属性对拷到原 reactive 对象,保持响应式
    Object.assign(jsonData, response.data)
  } catch (e) {
    // 网络错误、跨域被拦、后端 4xx/5xx 等都会进这里
    console.error('请求失败(先检查后端是否启动、是否跨域):', e)
    jsonData.content = '请求失败,请检查后端与跨域配置'
  }
}

/**
 * 生命周期:模板挂载完成后执行
 * 一进页面就自动拉一句情话
 */
onMounted(() => {
  getLoveMessage()
})
</script>

<template>
  <div class="page">
    <h2>今日土味情话</h2>
    <p class="content">{{ jsonData.content }}</p>
    <p class="meta" v-if="jsonData.code">编号:{{ jsonData.code }}</p>

    <!-- 点击再次请求;后端若做随机,每次内容可不同 -->
    <button type="button" @click="getLoveMessage">再来一句</button>
  </div>
</template>

<style scoped>
.page {
  max-width: 520px;
  margin: 40px auto;
  padding: 24px;
  text-align: left;
}

.content {
  font-size: 18px;
  line-height: 1.6;
  min-height: 3em;
  padding: 12px;
  background: #f6f8fa;
  border-radius: 8px;
}

.meta {
  color: #666;
  font-size: 14px;
}

button {
  margin-top: 12px;
  padding: 8px 16px;
  cursor: pointer;
}
</style>

代码解释:

3、程序入口

js 复制代码
/**
 * 应用入口:创建 Vue 应用并挂到页面
 * 本示例不需要路由 / Pinia,页面逻辑都在 App.vue
 */
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

createApp(App).mount('#app')

4、测试

三、详细介绍

0、先看全局:我们最终要会什么

text 复制代码
会分辨同步 / 异步
    ↓
会看 Promise 三状态(结果包装盒)
    ↓
会用 then / catch(或 async/await)处理成功失败
    ↓
会用 Axios 发请求,取出 response.data
    ↓
会赋给 Vue 的响应式数据并显示
    ↓
会处理跨域(前后端口不同时)

1、同步和异步:别让页面干等

同步 异步
含义 上一件不完,下一件不开始 先发出去,主流程继续;有结果再处理
类比 打电话:必须聊完才能干别的 发微信:发出去就能干别的,对方回了再看
前端请求 干等时页面体验差 日常开发默认用异步

定时器「两秒后再执行」也是异步:任务自己跑,主线程不等。

异步请求发出后,浏览器不用卡死;结果回来时,用回调处理即可。


2、Promise:异步结果的「状态盒」

Promise 是异步编程的一种解决方案:一次 Ajax 不论成功还是失败,都可以把结果状态装进这个盒子里。

它是 ES 里的一种对象类型,new Promise 的感觉接近 Java 里 new 一个对象。

2.1 Promise三个状态

状态 常见英文 何时出现
进行中 pending 请求已发出,结果还没回来
成功 fulfilled(通过 resolve 正常数据回来(如 HTTP 200)
失败 rejected(通过 reject 出错(4xx/5xx、网络失败等)

要点:

  • 最终落点只有两种:成功或失败;再加上「进行中」。
  • 不能既成功又失败,只能二选一。
  • 成功时把数据放进盒子;失败时通常是错误信息。

2.2 怎么创建一个 Promise

构造函数里传入回调,回调有两个参数,都是函数:

  • resolve(数据) → 保存成功
  • reject(错误) → 保存失败

参数名可以自定,关键是你调用了哪一个。

javascript 复制代码
const p = new Promise(function (resolve, reject) {
  // 二选一:
  resolve('后端返回的成功数据')
  // reject(new Error('失败了'))
})

2.3 用 then / catch 接结果

成功、失败都要用回调来接。两种写法:

写法 A:两个回调都放 then

javascript 复制代码
p.then(
  (value) => { /* 成功:value 就是 resolve 传来的值 */ },
  (err) => { /* 失败 */ }
)

写法 B:推荐------成功和失败分开,结构更清晰

javascript 复制代码
p.then((value) => {
  console.log('成功', value) // 拿到数据后想干嘛自己定
}).catch((err) => {
  console.log('失败', err)   // 一般是 Error
})

说明:业务里很少手写 new Promise,但 Axios 返回的就是 Promise,所以三状态和 then/catch 必须懂。真正写项目时,重点往往在「成功回调里怎么用数据」。


3、async:让函数自动返回 Promise

async / await 是更晚的 ES 语法关键字。先看 async

3.1 加了 async,返回值会发生什么

javascript 复制代码
async function getTen() {
  return 10
}

const result = getTen()
// result 不是数字 10,而是一个 Promise
// 相当于:成功结果为 10 的 Promise

可以对比后端「统一 Result」:真实数据被包了一层,这一层表示成功或失败。

函数内部 调用方拿到的 Promise
return 普通值 成功,值为该值
throw new Error('...') 失败(前端统一用 Error
return 已有的 Promise 沿用该 Promise 的成功/失败
javascript 复制代码
async function ok() {
  return 10
}
async function fail() {
  throw new Error('出错了')
}

ok().then((v) => console.log(v))       // 10
fail().catch((e) => console.log(e))    // Error

3.2 async 带来的好处

不必到处手写 new Promise:直接返回数据或抛错,运行时帮你包装成 Promise。

拿到 Promise 后,再用 then / catch 处理(二者只会走一边)。


4、await:等结果回来再往下走

await 的字面意思就是等待

4.1 为什么要等

假设 fun2 里要用到 fun1 的返回值:

javascript 复制代码
async function fun1() {
  return 10 // 被包装成成功 Promise
}

async function fun2() {
  const res = await fun1()
  // 等 fun1 完成;成功时 res 直接是 10,不是 Promise 对象
  console.log(res) // 10
  // 后面的代码依赖 res,所以必须等
}

如果去掉 awaitfun1 异步执行,下一行可能已经跑了,此时 res 还没就绪------拿不到真正的值。

4.2 必须记住的规则

规则 说明
await → 函数必须是 async 否则报错
async → 可以没有 await 允许
await 右侧多为 Promise 普通值也可以
右侧 Promise 失败 抛异常,用 try/catch 捕获
javascript 复制代码
async function demo() {
  try {
    const data = await someAsyncCall()
    console.log(data) // 成功值
  } catch (e) {
    console.log('失败', e) // 不必再手写一长串 then/catch
  }
}

await 会卡住当前这段异步函数的后续语句:右边没结束,后面先不执行。

4.3 async + await 一起用的本质

  1. async:把返回值进 Promise
  2. await:把成功 Promise成真实值

中间封/拆不用自己管,所以一般不必再 new Promise + then。这就是日常推荐写法。


5、Axios:真正向后端要数据

Axios 是基于 Promise 的网络请求库,封装了 Ajax,可在浏览器 / Node 中使用。

5.1 相关概念

名词 含义
Ajax Asynchronous JavaScript And XML,异步请求的统称
数据格式 早期常见 XML,现在主流是 JSON
XMLHttpRequest 浏览器侧异步请求对象
Axios 帮你发请求、用 Promise 包装结果,还可配合拦截器等

注意:浏览器发异步请求,后端该怎么分层还怎么分层;变的是前端交互------不必整页干等,结果回来做局部更新即可。

5.2 安装

bash 复制代码
npm i axios
npm run dev

5.3 最小请求写法

javascript 复制代码
import axios from 'axios' // 默认导出,变量名可叫 axios / http

axios({
  method: 'get', // get查询 / post添加 / put修改 / delete删除
  url: 'http://localhost:8080/api/情话',
  // params: { username: 'admin' }, // 拼到 URL ?key=value,GET 常用
  // data: { username: 'admin' },   // 放请求体,POST 常用
})
  .then((response) => {
    console.log(response.data) // 业务 JSON 在 data 里
  })
  .catch((error) => {
    console.log(error)
  })
配置 作用
method 请求方式
url 后端地址
params 查询参数(URL 后);后端常用 @RequestParam
data 请求体;后端常用 @RequestBody

Axios 调用返回 Promise ,因此可以接 then/catch,也可以 await


6、接到 Vue:土味情话示例

需求示例:后端 http://localhost:8080/api/情话 返回 { code, content },页面显示情话,按钮可再刷一句。

6.1 推荐实现顺序

text 复制代码
准备 reactive 模型
  → 编写请求函数(axios + await)
  → onMounted 进页拉一次
  → 按钮再拉一次
  → Object.assign 写入模型
  → 模板绑定 content

6.2 完整代码

html 复制代码
<script setup>
import { reactive, onMounted } from 'vue'
import axios from 'axios'

const jsonData = reactive({
  code: 0,
  content: '',
})

async function getLoveMessage() {
  try {
    const response = await axios({
      method: 'get',
      url: 'http://localhost:8080/api/情话',
    })
    // response:完整响应对象
    // response.data:后端 JSON
    Object.assign(jsonData, response.data)
  } catch (e) {
    console.log('请求失败', e)
  }
}

onMounted(() => {
  getLoveMessage() // 模板就绪后要数据
})
</script>

<template>
  <div>
    <h3>今日土味情话</h3>
    <p>{{ jsonData.content }}</p>
    <button type="button" @click="getLoveMessage">再来一句</button>
  </div>
</template>

6.3 成功回调里到底拿到什么

text 复制代码
response                 ← Axios 给的响应对象
  ├─ status / headers ...
  └─ data                ← 后端返回的 JSON
       ├─ code
       └─ content        ← 页面要显示的字段

若后端还有统一 Result 包装:

text 复制代码
response.data        → Result
response.data.data   → 真正业务数据(可能需要点两层 data)

调试建议:先 console.log(response),或在 Network / 断点里看对象结构,再决定取哪一层。

6.4 赋值方式:保住响应式

javascript 复制代码
// 错误:整对象替换,引用变了,响应式容易失效
// jsonData = backData

// 正确:属性拷贝到原对象上
Object.assign(jsonData, backData)

// 字段很少时也可以:
// jsonData.code = backData.code
// jsonData.content = backData.content

6.5 什么时候必须 await

若请求后面还要立刻使用数据(例如打印、二次计算),必须 await,并且函数声明为 async

若后面没有任何依赖结果的代码,可以不 await。

不加 await 就往下跑,常见现象:打印出来仍是空对象------数据还没赋上去。


7、跨域:5173 访问 8080 被拦截

前端开发服务器(如 5173)和后端(如 8080)只要协议 / 域名 / 端口有一个不同,就是跨域。浏览器会拦截不安全的跨源请求。

典型报错关键词:

text 复制代码
CORS policy / blocked / Access-Control-Allow-Origin

开发期常见处理(Java 后端示例):在 Controller 上允许跨域:

java 复制代码
@CrossOrigin
@RestController
public class LoveController {
  // ...
}

放行后响应头会出现类似 Access-Control-Allow-Origin: *,请求才能进入成功回调。

生产环境通常配置更精确的允许来源,或用网关 / 反向代理。


8、底层:这些对象住在哪里

名字 更像存在哪 内容
变量 response 栈上的引用 指向堆对象
Promise 状态 + 成功值 / 失败原因
response 对象 status、headers、data...
response.data 业务 JSON
reactive(jsonData) 堆中的响应式对象 Object.assign 改字段、不换地址
text 复制代码
await axios(...)
  → Promise:pending → fulfilled
  → 得到 response
  → 取出 data
  → 拷贝进 reactive
  → 视图更新

OK,本期我们先介绍到这里,下一期我们将补充Axios的get和post请求以及拦截器等等工作。

相关推荐
古韵1 天前
axios 已经跑得好好的,还要不要上 alova?
前端·javascript·axios
弹简特1 天前
【Vue3速成】06-vue3官方库路由机制之Pinia状态管理
vue·pinia
java1234_小锋2 天前
Vue3专题 - 响应式基础
vue·vue3·响应式
Wiktok2 天前
Vue3(Vite)打包安卓APP 完整最佳实践
android·vue
sugar__salt2 天前
Vue3 自定义指令与插槽(Slot)技术详解
前端·javascript·vue.js·前端框架·vue
万亿少女的梦1683 天前
基于Vue、Vite与CesiumJS的江西省铜矿资源WebGIS系统设计
vue·vite·cesiumjs·webgis·空间数据可视化
目送卷王离开3 天前
前端接 LLM 流式输出:EventSource、axios、fetch 怎么选
axios
天丁o3 天前
我把一套 Flowable + Spring Boot + Vue 的 BPM 流程引擎整理开源了:从流程设计器到待办闭环
spring boot·vue·工作流引擎·flowable·bpm流程引擎·流程审批
弹简特3 天前
【Vue3速成】05-vue3官方库路由机制之路由守卫
vue·路由