国庆节10月1日
--


Axios 是对原生 Ajax 的封装——引一个 js 文件,用 axios.get 或 axios.post 就能向服务器要数据,配合 async 与 await 把回调写成同步的样子,是前后端分离里前端取数的标准动作

20 篇的 empList 是写在 data 里的死数据——改一条员工就得改一次代码。可真实项目里数据在服务器上、在数据库里,页面上那些数字还会随时变。这一篇解决的就是”怎么向服务器要数据”:
async / await 怎么写才顺眼,以及和真实接口对接时那几个必踩的坑。22 篇会把这些全用到员工列表案例上。
介绍(PPT 原文):Asynchronous JavaScript And XML——异步的 JavaScript 和 XML。
拆开两个词:
| 词 | 意思 |
|---|---|
| Asynchronous(异步) | 请求发出去以后不用干等着,页面该干嘛干嘛(下面一节专门讲”同步 vs 异步”) |
| JavaScript And XML | 用 JS 来发请求、用 XML 这种格式来装数据 |
XML(PPT 的注解):(英语:Extensible Markup Language)可扩展标记语言,本质是一种数据格式,可以用来存储复杂的数据结构。
这个名字是”历史遗留”:Ajax 诞生那会儿后端返回的数据确实是用 XML 装的。现在实际开发里几乎都用 JSON(15 篇里那种”数组里放对象”的格式就是 JSON 的样子)。名字没变,装的格式换了——看到 XML 两个字别慌,知道它是”一种数据格式”就够了。
Ajax 的作用(PPT 列了两条,都很关键):
“异步交互”听着抽象,PPT 配了两个大家天天在用的例子:

java,下拉框里立刻冒出”java线下培训""java版我的世界”等联想词;这些词不在本地,是每敲一个字就悄悄找服务器要一次,而页面本身完全没有刷新(地址栏没变、你打的字也没丢)
这两个例子的共同点:局部更新。要是没有 Ajax,得”提交表单 → 整页刷新 → 页面把所有内容重新渲染一遍”,体验完全不同。
PPT 第 31 页用一张时间轴图(左同步、右异步)对比”请求服务器要 3 秒”时客户端在干什么:
| 同步(Synchronous) | 异步(Asynchronous) | |
|---|---|---|
| 客户端时间线 | 1. 正在访问… → 2. 请求服务器… → 3. 服务器处理中(3s) → 4. 响应客户端… → 5. 继续访问… | 1. 正在访问… → 2. 请求服务器… → 2/3. 客户端可以执行其他操作… → 4. 响应客户端… → 5. 继续访问 |
| 等待这 3 秒时页面能干什么 | 什么都干不了,卡在那里等(前面那些步骤得按顺序走完) | 页面照常能用:你可以继续打字、滚动、点别的按钮;服务器回话以后再去处理结果 |
| 一句话 | 一步一步等,前一步不做完后一步不开始 | 先把请求发出去,不耽误干别的事,结果回来了再处理 |
异步在代码里长什么样?看课程 15. Axios-请求方式别名.html 里这几行——注意打印顺序:
1axios.get('...').then((result) => {2 console.log(result.data); // ② 服务器回话了才执行(可能是一秒以后)3});4console.log('=========================='); // ① 这行会先打印!明明 .then(...) 写在前面,但 ========== 先出现在控制台——因为 .then() 里的函数是”结果回来以后才执行的回调函数”,而它下面的代码不用等。这就是异步:发起请求不阻塞后面的代码。
后面学的 async / await 就是给这种写法”改口味”的(让代码读起来像从上往下一步步执行)。
介绍(PPT 原文):Axios 对原生的 Ajax 进行了封装,简化书写,快速开发。(官网:https://www.axios-http.cn/)
用 17 篇的 addEventListener 类比一下:原生的 Ajax 是 XMLHttpRequest,写起来又长又啰嗦(要判断 readyState、手动 JSON.parse);Axios 把它包了一层,发请求这件事变成一行。
使用步骤(PPT 原文就两步):
引入方式(PPT 给的是在线地址;课程代码用的是本地文件):
1<!-- 方式一:在线引入(和 Vue 一样,直接写 CDN 地址) -->2<script src="https://unpkg.com/axios/dist/axios.min.js"></script>3
4<!-- 方式二:本地引入(课程 js 目录里就有一份 axios.js) -->5<script src="js/axios.js"></script>注意和前一篇的区别:Axios 的引入不用 type="module"——它是普通脚本(把 axios 挂成全局变量),所以:
axios.get(...),不需要 import。练习文件里的 Axios 也是直接 <script src="..."> 引入的,双击就能用(联网即可)。
课程 14. Axios-入门.html 的写法(页面上两个按钮,点一下发一次请求):
1<script src="js/axios.js"></script>2<script>3 //发送GET请求4 document.querySelector('#btnGet').addEventListener('click', () => {5 //axios发起异步请求6 axios({7 url: 'https://mock.apifox.cn/m1/3083103-0-default/emps/list',8 method: 'GET'9 }).then((result) => { //成功回调函数10 console.log(result.data);11 }).catch((err) => { //失败回调函数12 console.log(err);13 })14 })15
16 //发送POST请求17 document.querySelector('#btnPost').addEventListener('click', () => {18 //axios发起异步请求19 axios({20 url: 'https://mock.apifox.cn/m1/3083103-0-default/emps/update',21 method: 'POST',22 data: 'id=1' //POST请求方式 , 请求体23 }).then((result) => { //成功回调函数24 console.log(result.data);25 }).catch((err) => { //失败回调函数26 console.log(err);27 })28 })29</script>axios({ ... }) 里那个对象是请求配置,PPT 把常用的四个参数列了出来:
| 配置项 | 含义 |
|---|---|
method | 请求方式:GET / POST(后面还有 PUT、DELETE 等) |
url | 请求路径(接口地址) |
data | 请求数据(POST)——放在请求体里 |
params | 发送请求时携带的 url 参数,如 ...?key=val(拼在地址后面的那种) |
后面的两个方法(PPT 标注为”成功回调函数 / 失败回调函数”):
| 写法 | 什么时候执行 | 拿到什么 |
|---|---|---|
.then((result) => { ... }) | 请求成功(服务器正常返回) | result 是响应对象,业务数据在 result.data 里 |
.catch((err) => { ... }) | 请求失败(断网、地址写错、服务器报错……) | err 是错误对象,console.log 出来能看原因 |
上面两段课程代码里的地址(https://mock.apifox.cn/m1/3083103-0-default/...)是第三方 mock(假接口)平台给的演示地址——课程用它是因为”能立刻返回一段 JSON 数据、练手方便”。mock 平台上的地址有失效的可能,打不开时换成课程的教学接口即可:
https://web-server.itheima.net/emps/list(支持 ?name=xxx&gender=xxx&job=xxx 三个查询条件)https://web-server.itheima.net/emps/update(POST,请求体如 id=1)这两个接口都是”教学演示”用的,返回结构和 mock 地址一致(都是 {code, msg, data})。笔记的练习文件统一用这两个地址。
这是最容易搞混的地方:result 不是数据本身,result.data 才是服务器返回的内容。
1axios.get('https://web-server.itheima.net/emps/list').then((result) => {2 console.log(result.data); // 服务器返回的"全部内容"3});result 这个响应对象里装着几样东西:
| 属性 | 是什么 |
|---|---|
result.data | 服务器返回的响应体(业务数据在这里) |
result.status | HTTP 状态码(200 表示成功) |
result.statusText | 状态码对应的文字(如 OK) |
result.headers | 响应头 |
result.config | 本次请求的配置(就是 axios({...}) 里写的那份) |
而这门课后端返回的 result.data 自己又包了一层(这是后端接口的”统一返回格式”),长这样:
1{2 "code": 1,3 "msg": "success",4 "data": [ { "id": 1, "name": "谢逊", ... }, ... ]5}code:业务状态码(1 表示成功)msg:提示信息data:真正的业务数据所以取员工列表要写两层:result.data.data。
| 想要的东西 | 写法 |
|---|---|
| 服务器返回的全部内容(含 code/msg) | result.data |
| 员工数组(真正要渲染的) | result.data.data |
报错 Cannot read properties of undefined (reading 'xxx') 时先怀疑这里:
result.data 但接口返回的是”包了一层”的结构 → 应该写 result.data.data;empList,你按 data 取)。
办法很土但最有效:先把 console.log(result) 和 console.log(result.data) 打出来看清楚结构,再决定写几层。PPT 第 33 页:为了方便起见,Axios 已经为所有支持的请求方法提供了别名。
格式:axios.请求方式(url [, data [, config]])——PPT 标注”推荐”,因为比 axios({...}) 短得多。
课程 15. Axios-请求方式别名.html 的写法:
1<script src="js/axios.js"></script>2<script>3 //发送GET请求4 document.querySelector('#btnGet').addEventListener('click', () => {5 axios.get('https://mock.apifox.cn/m1/3083103-0-default/emps/list').then((result) => {6 console.log(result.data);7 });8 console.log('==========================');9 })10
11 //发送POST请求12 document.querySelector('#btnPost').addEventListener('click', () => {13 axios.post('https://mock.apifox.cn/m1/3083103-0-default/emps/update', 'id=1').then((result) => {14 console.log(result.data);15 });16 })17</script>两种写法完全等价,对比一下:
1// 原始写法:一个对象,四个参数都写在里面2axios({3 url: 'https://web-server.itheima.net/emps/list',4 method: 'GET',5 params: { name: '谢逊' }6}).then(...)7
8// 别名写法:GET 的参数用 params 配置项接9axios.get('https://web-server.itheima.net/emps/list', {10 params: { name: '谢逊' }11}).then(...)完整别名表(PPT 第 33 页说的”所有支持的请求方法”,按 axios 官网的清单):
| 别名 | 参数形式 | 说明 |
|---|---|---|
axios.get(url[, config]) | 地址 + 配置 | 用来获取数据,参数走 config.params |
axios.delete(url[, config]) | 地址 + 配置 | 删除,参数同样走 config.params |
axios.head(url[, config]) | 地址 + 配置 | 只取响应头 |
axios.options(url[, config]) | 地址 + 配置 | 预检请求 |
axios.post(url[, data[, config]]) | 地址 + 数据 + 配置 | 提交/新增,数据放在请求体 |
axios.put(url[, data[, config]]) | 地址 + 数据 + 配置 | 整体修改,数据放请求体 |
axios.patch(url[, data[, config]]) | 地址 + 数据 + 配置 | 局部修改,数据放请求体 |
看规律:GET 系列(get / delete / head / options)第二个参数是”配置”;POST 系列(post / put / patch)第二个参数是”数据”、第三个才是配置。
课程里 GET 用的是 https://web-server.itheima.net/emps/list、POST 用的是 .../emps/update(同一个服务器的不同接口)。别把 get 和 post 和”取/存”这两个语义绑死在一张表上——用什么方式,看接口文档写的什么,不是看你想干什么。
PPT 原文:可以通过
async、await可以让异步变为同步操作。async就是来声明一个异步方法,await是用来等待异步任务执行。
async:加在函数前面的关键字,声明”这是一个异步方法”,函数里就可以用 await 了;await:等着异步任务的结果——它取代了 .then(),而且只在 async 函数内有效。对比同一件事的两种写法:
1// 写法一:.then() 回调(结果在 then 的括号里才拿得到)2methods: {3 search() {4 axios.get('https://web-server.itheima.net/emps/list').then((result) => {5 this.empList = result.data.data; // 注意:这里的 this 要靠箭头函数才指向 Vue 实例6 });7 }8}1// 写法二:async / await(结果直接赋值给变量,一行一句)2methods: {3 async search() { // ① 方法前加 async4 let result = await axios.get('https://web-server.itheima.net/emps/list'); // ② await 等结果5 this.empList = result.data.data; // ③ 下一行直接用结果6 }7}PPT 对第二种评价是:可读性强、便于维护——代码从”回调套回调”变成”从上到下一行接一行”。
这篇的课程案例代码(16. Vue-案例-员工列表(异步交互).html 里的 search 方法,PPT 第 37 页就是这段):
1methods: {2 async search() {3 //根据用户输入的搜索条件,基于axios发送异步请求(https://web-server.itheima.net/emps/list)到服务端...4 let result = await axios.get('https://web-server.itheima.net/emps/list?name=xxx&gender=xxx&job=xxx');5 this.employees = result.data.data;6 }7}注意(PPT 原文):await 关键字只在 async 函数内有效,await 关键字取代 then 函数,等待获取到请求成功的结果值。
await 的三个常见坑:
async 函数里用 await——语法错误,页面直接不工作。函数前面加上 async 就好。async 没加 await——let result = axios.get(...) 拿到的是”尚未完成的请求对象”(Promise),result.data 是 undefined。两者要成对出现。.catch() 了,出错怎么办?——async / await 里 then / catch 那一套不用了,错误用 try...catch 接:
1async search() {2 try {3 let result = await axios.get('https://web-server.itheima.net/emps/list');4 this.empList = result.data.data;5 } catch (err) {6 console.log(err); // 断网、接口没起来、地址写错,都会走到这里7 alert('数据加载失败,请稍后重试');8 }9}try/catch,但真实项目里该写——不然接口一挂,页面上什么提示都没有。)这一节是”能跑通”和”跑不通”之间的分界线。前端发请求失败,八成的锅在这几条上:
浏览器有同源策略:协议、域名、端口三者只要有一个不同,就属于”跨域”请求,浏览器会额外检查服务端有没有”允许你这个来源访问”的响应头。
http://127.0.0.1:5500)去请求 https://web-server.itheima.net/...——域名和端口都不同,就是跨域;Access-Control-Allow-Origin: *(允许任何来源),所以能正常拿到数据;has been blocked by CORS policy,.catch 里拿到的是 Network Error。后面学 SpringBoot 时,这事有正经解法(后端加跨域配置 / 用 @CrossOrigin,前端工程化项目里还有”代理”这一招)。现在只要会认这个错:控制台出现 CORS policy → 找后端(或问 AI)配允许跨域,不是前端代码写错了。
| 要核对 | 例子 | 错了会怎样 |
|---|---|---|
| 地址(url) | https://web-server.itheima.net/emps/list | 404 Not Found |
| 请求方式(method) | 接口要 GET,你写了 POST | 405 Method Not Allowed |
| 参数名 | 接口要 name / gender / job | 参数被当成没用上,返回的是全量数据(或空数据) |
| 参数位置 | GET 拼在地址后面(?name=xxx 或 config.params);POST 放在请求体(data) | 后端读不到参数 |
案例里 GET 的查询参数是用模板字符串拼到地址上的(20 篇学的反引号):
1// 三个条件拼在 ? 后面,用 & 连接2let url = `https://web-server.itheima.net/emps/list?name=${this.searchForm.name}&gender=${this.searchForm.gender}&job=${this.searchForm.job}`;3let result = await axios.get(url);参数里有中文、空格、& 这类字符时,正规做法是 encodeURIComponent(...) 包一层(浏览器通常会自动处理,但自己包上更稳):
1let url = `https://web-server.itheima.net/emps/list?name=${encodeURIComponent(this.searchForm.name)}`;另一个更省事的写法是把参数交给 axios 去拼:
1let result = await axios.get('https://web-server.itheima.net/emps/list', {2 params: { name: this.searchForm.name, gender: this.searchForm.gender, job: this.searchForm.job }3});(课程案例用的是模板字符串那种,两种都对。)
result.data 还是 result.data.data,取决于后端包了几层——先 console.log 看清楚再写(前面那一节讲过)。
练这一章时最常见的场景:后端没启动、地址写错、断网。这时候的现象一定要会认——因为”看着像白屏”的锅常常不在你的代码:
| 情况 | 控制台/页面表现 | 该检查什么 |
|---|---|---|
| 后端没启动(本地接口) | .catch 里 err.message 是 Network Error;F12 的 Network 面板里这条请求是红色失败 | 后端项目启动了没?端口对不对(如 8080)? |
| 地址写错 / 接口不存在 | Request failed with status code 404 | url 拼得对不对(少个 /、少个 list 都会 404) |
| 请求方式不对 | Request failed with status code 405 | method 和接口文档一致吗 |
| 跨域被拦 | 报 blocked by CORS policy,.catch 里是 Network Error | 后端配了跨域吗(见上面第 1 条) |
| 断网 / CDN 打不开 | Failed to load resource: net::ERR_INTERNET_DISCONNECTED;如果 Vue 或 axios 本身是从 CDN 引的,连页面都动不了 | 联网状态;或用本地 js 文件 + Live Server |
| 都不报错但表格是空的 | 页面正常、控制台没红字,就是没数据 | ①返回的是不是”包一层”的结构(result.data.data);②筛选条件是不是把数据都筛掉了(比如 name 传了空串以外的值但没匹配) |
写这一章的代码时,养成”先看控制台、再看 Network 面板”的习惯:报错信息里其实写清了原因(404/405/CORS/Network Error),比”页面没反应”这句描述有用一百倍。接口暂时用不了时,页面该有的表现是表格空白 + 控制台一条错误——22 篇的提示块里还给了”怎么给用户一个友好的失败提示”。
| 问题 | 答案 |
|---|---|
| Ajax 是什么? | Asynchronous JavaScript And XML(异步的 JavaScript 和 XML);XML 本质是一种数据格式(现在实际都用 JSON) |
| Ajax 的作用? | ① 数据交换:给服务器发请求、拿服务器响应的数据;② 异步交互:不重新加载整个页面的情况下交换数据并更新部分网页(搜索联想、用户名是否可用校验) |
| 同步和异步的区别? | 同步要等着服务端处理完才继续(页面卡住);异步发出去就不管了,期间客户端可以执行其他操作,结果回来了再处理(.then 里的代码会后执行) |
| Axios 是什么? | 对原生 Ajax 的封装,简化书写、快速开发(官网 https://www.axios-http.cn/);两步:**引入 js 文件** → 发送请求并获取响应结果 |
| 怎么引入? | <script src="https://unpkg.com/axios/dist/axios.min.js"></script> 或本地的 <script src="js/axios.js"></script>——普通脚本,不用 type="module",双击 html 也能用 |
| 基本写法? | axios({ method: 'GET', url: '...', data: '...', params: {...} }).then(result => {...}).catch(err => {...});method 请求方式、url 路径、data 请求体(POST)、params url 参数 |
| 别名写法? | axios.请求方式(url [, data [, config]])(推荐):axios.get(url[, config]) / axios.delete / axios.head / axios.options / axios.post(url[, data[, config]]) / axios.put / axios.patch |
| 结果怎么取? | 成功回调里业务数据在 result.data(响应对象还有 status/headers/config);课程后端”包了一层”,所以员工数组是 result.data.data |
| async / await 怎么写? | 方法前加 async,请求前加 await:let result = await axios.get(url);——await 只在 async 函数内有效、取代 .then();错误用 try...catch 接 |
| 对接接口要注意什么? | ① 跨域 CORS(协议/域名/端口任一不同;接口要允许跨域,控制台报 blocked by CORS policy);② 地址、请求方式、参数名、参数位置要和接口文档一致;③ 返回值层数(result.data 还是 result.data.data);④ 接口没起来时是 Network Error / 404 / 405,页面空白+控制台报错 |
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>(在线)或 <script src="js/axios.js"></script>(本地);是普通脚本(不用 type="module"、不用 import),全局 axios 直接用axios({ method, url, data, params }).then(成功回调).catch(失败回调)——method 请求方式、url 请求路径、data 请求数据(POST 请求体)、params url 参数(?…&…)axios.请求方式(url [, data [, config]]),推荐;axios.get(url[, config])、axios.delete、axios.head、axios.options 第二个参数是配置;axios.post(url[, data[, config]])、axios.put、axios.patch 第二个参数是数据result 是响应对象(有 data / status / statusText / headers / config);业务数据在 result.data;课程后端统一返回 {code, msg, data},所以员工数组是 result.data.dataasync 声明异步方法,await 等待异步任务成功的结果值并取代 .then();await 只在 async 函数内有效;代码可读性强、便于维护;错误用 try...catch 捕获blocked by CORS policy);② 地址/请求方式/参数名/参数位置和接口文档一致;③ 返回值的层数(先 console.log 看清楚);④ 接口没起来时表现为 Network Error、404、405——页面空白 + 控制台报错2-1 点按钮从服务器拿数据 页面上有一个”获取员工数据”按钮和一个输出区。要求:
https://web-server.itheima.net/emps/list)test_21_发送GET请求.html 里已经准备好了按钮、输出区和 Axios 引入。)一级 · 思路:一次请求 = 地址 + “要数据”这个动作;结果要”先看清楚结构再取值”,因为返回的内容外面包了一层
二级 · 方法:axios.get(地址);成功用 .then((result) => {...}),先 console.log(result.data) 看结构;员工数组在 result.data.data;人数用 .length;失败用 .catch((err) => {...})
三级 · 骨架:axios.____('https://web-server.itheima.net/emps/list').____((result) => { console.log(result.____); document.querySelector('#out').innerText = \共 ${result.data.data.} 人`; }).((err) => { ……’加载失败’…… })`
1<button type="button" id="btn">获取员工数据</button>2<p id="out"></p>3
4<script src="https://unpkg.com/axios/dist/axios.min.js"></script>5<script>6 document.querySelector('#btn').addEventListener('click', () => {7 axios.get('https://web-server.itheima.net/emps/list')8 .then((result) => {9 console.log(result.data); // 控制台里看清楚:{code, msg, data:[...]}10 // 员工数组在 result.data.data 里11 document.querySelector('#out').innerText = `共 ${result.data.data.length} 人`;12 })13 .catch((err) => {14 console.log(err);15 document.querySelector('#out').innerText = '加载失败';16 });17 });18</script>检查点:① 点按钮后输出区显示”共 4 人”(当前接口里有 4 条数据);② 控制台里能看到 {code: 1, msg: "success", data: Array(4)};③ 故意把地址改错一个字母再点,页面显示”加载失败”、控制台里有 404 报错——这就是”接口没起来/地址写错”的表现。
2-2 用别名写法提交一次数据 页面上有一个”提交修改”按钮。要求:
https://web-server.itheima.net/emps/update 提交一份数据(请求体内容就写 id=1)https://web-server.itheima.net/emps/list),并把返回的 msg 字段显示到页面上
(练习文件 test_21_请求方式别名.html 里已经准备好了按钮、输出区和写作区。)一级 · 思路:别名就是”用方法名表示请求方式”;第二个参数的位置决定传进去的是”要提交的数据”还是”配置”
二级 · 方法:axios.post(地址, 数据)——提交的数据放在第二个参数;axios.get(地址) 拿数据;显示用 document.querySelector('#out').innerText = result.data.msg
三级 · 骨架:axios.____('https://web-server.itheima.net/emps/update', '____').then((result) => { console.log(result.____); }); / axios.____('https://web-server.itheima.net/emps/list').then((result) => { document.querySelector('#out').innerText = result.data.____; });
1<button type="button" id="btnPost">提交修改</button>2<button type="button" id="btnGet">获取列表</button>3<p id="out"></p>4
5<script src="https://unpkg.com/axios/dist/axios.min.js"></script>6<script>7 // 提交数据:别名 post,第二个参数就是请求体数据8 document.querySelector('#btnPost').addEventListener('click', () => {9 axios.post('https://web-server.itheima.net/emps/update', 'id=1').then((result) => {10 console.log(result.data); // {code: 1, msg: "success", data: null}11 });12 });13
14 // 获取数据:别名 get,把返回的 msg 显示到页面15 document.querySelector('#btnGet').addEventListener('click', () => {16 axios.get('https://web-server.itheima.net/emps/list').then((result) => {17 document.querySelector('#out').innerText = result.data.msg;18 });19 });20</script>检查点:① 点”提交修改”控制台打印 msg: "success";② 点”获取列表”页面显示 success;③ 能说出 axios.post(url, data) 里第二个参数为什么是数据——因为 POST 的”要提交的东西”是它的第一个业务参数(对比 axios.get(url, config) 的第二个参数是配置)。
对照课程 15. Axios-请求方式别名.html。课程里在那句 axios.get(...) 后面还写了一行 console.log('==========================')——它会先打印,这正是”异步”的证据,自己加进去验证一遍。
2-3 用 async / await 改写,并做错误处理 页面上有一个”查询”按钮和一个输出区。要求:
https://web-server.itheima.net/emps/list,把员工姓名拼成一句话显示到输出区(如”谢逊, 韦一笑, 黛绮丝, 殷天正”)async / await 的写法(不许用 .then())test_21_async_await.html 里已经准备好了按钮、输出区和写作区。)一级 · 思路:把”要等的异步任务”用 await 接住,结果就变成一个普通变量;出错的路用 try / catch 分成两段
二级 · 方法:函数前加 async;let result = await axios.get(地址);数组 .map() 或用 for 拼姓名;try { … } catch (err) { … };console.log 用来看顺序
三级 · 骨架:async function load() { try { console.log('开始'); let result = ____ axios.get('……/emps/list'); let names = result.data.data.map(e => e.____).join(', '); document.querySelector('#out').innerText = ____; console.log('结束'); } catch (____) { console.log(err); document.querySelector('#out').innerText = '数据加载失败,请检查网络或接口地址'; } }
1<button type="button" id="btn">查询</button>2<p id="out"></p>3
4<script src="https://unpkg.com/axios/dist/axios.min.js"></script>5<script>6 // async:声明这是一个异步方法,里面才能用 await7 async function load() {8 try {9 console.log('① 开始请求');10 // await:等请求成功的结果,取代 .then()11 let result = await axios.get('https://web-server.itheima.net/emps/list');12 // 把姓名数组拼成一句话13 let names = result.data.data.map(e => e.name).join(', ');14 document.querySelector('#out').innerText = names;15 console.log('② 请求完成');16 } catch (err) {17 // 断网、地址写错、跨域被拦都会走到这里18 console.log(err);19 document.querySelector('#out').innerText = '数据加载失败,请检查网络或接口地址';20 }21 }22
23 document.querySelector('#btn').addEventListener('click', load);24</script>检查点:① 页面显示”谢逊, 韦一笑, 黛绮丝, 殷天正”(接口返回 4 条;条数可能变,以实际为准);② 控制台顺序是”① 开始请求 → ② 请求完成”(多了 await,打印顺序和 .then() 那种写法不一样);③ 把地址改错后点查询,页面显示失败提示、控制台有报错,页面没有卡死。
3-1 做一个”接口小工具”页面(GET 查询 + POST 提交 + 状态提示) 页面上有三个区域:一个姓名输入框 + 查询按钮 + 清空按钮、一块结果区、一个”提交一条数据”按钮。要求(按步骤来):
async / await 向 https://web-server.itheima.net/emps/list 发 GET 请求,并把姓名输入框里的内容作为 name 参数拼到地址后面(?name=xxx)https://web-server.itheima.net/emps/update 提交 id=1,把返回的 msg 显示在结果区最后一行try / catch 处理错误,并在控制台打印每次请求的完整响应(先看清楚结构再取数据)
(练习文件 test_21_综合_接口小工具.html 里已经准备好了页面结构和写作区。)一级 · 思路:把”发请求”包成一个函数,界面上的每个按钮只负责”改一下状态 + 调这个函数”;界面上所有文字都靠”改 DOM 内容”或”改元素内容”来更新
二级 · 方法:async function load() { try { … await axios.get(url) … } catch (err) { … } };拼参数用模板字符串 `...?name=${name}`;渲染列表用 数组.map(item => \
再赋给innerHTML([16 篇](/posts/编程学习/javaweb学习笔记/16-js-dom操作/)的套路);POST 用 axios.post(url, data);状态提示就是改某个元素的 innerText **三级 · 骨架**:async function load() { out.innerText = ''; try { let result = await axios.(`https://web-server.itheima.net/emps/list?name=${____}\`); let list = result.data.data; if (list.length == 0) { out.innerText = ‘没有匹配的员工’; } else { out.innerHTML = list.(e => `1<input type="text" id="name" placeholder="请输入姓名">2<button type="button" id="btnSearch">查询</button>3<button type="button" id="btnClear">清空</button>4<button type="button" id="btnUpdate">提交一条数据</button>5
6<div id="status"></div>7<ul id="list"></ul>8
9<script src="https://unpkg.com/axios/dist/axios.min.js"></script>10<script>11 let statusBox = document.querySelector('#status');12 let listBox = document.querySelector('#list');13
14 // ① + ② + ③ 查询、渲染、状态提示15 async function load() {16 statusBox.innerText = '加载中…'; // 请求前:先给用户一个反馈17 try {18 let name = document.querySelector('#name').value;19 let result = await axios.get(`https://web-server.itheima.net/emps/list?name=${name}`);20 console.log(result.data); // 先看清楚结构:{code, msg, data}21
22 let emps = result.data.data;23 if (emps.length == 0) {24 statusBox.innerText = '没有匹配的员工';25 listBox.innerHTML = '';26 } else {27 statusBox.innerText = `共 ${emps.length} 人`; // 请求成功:提示换了内容28 listBox.innerHTML = emps.map(e => `<li>${e.name} - ${e.entrydate}</li>`).join('');29 }30 } catch (err) {31 console.log(err);32 statusBox.innerText = '加载失败:' + err.message;33 }34 }35
36 // ④ 清空:输入框擦掉、结果区回到初始提示37 function clear() {38 document.querySelector('#name').value = '';39 statusBox.innerText = '请输入姓名后点击查询';40 listBox.innerHTML = '';41 }42
43 // ⑤ 提交:POST,数据放在第二个参数44 async function update() {45 try {46 let result = await axios.post('https://web-server.itheima.net/emps/update', 'id=1');47 console.log(result.data);48 statusBox.innerText = '提交结果:' + result.data.msg;49 } catch (err) {50 console.log(err);51 statusBox.innerText = '提交失败:' + err.message;52 }53 }54
55 // 页面一打开就给个初始提示(还没学 Vue 的 mounted,这里直接手动调一次)56 clear();57
58 document.querySelector('#btnSearch').addEventListener('click', load);59 document.querySelector('#btnClear').addEventListener('click', clear);60 document.querySelector('#btnUpdate').addEventListener('click', update);61</script>检查点:① 打开页面结果区显示”请输入姓名后点击查询”;② 姓名填”谢”再查询,列表出现匹配的员工行(参数没生效就会返回全部 4 条——可以对比一下);③ 姓名填一个乱码(如 zzz)查询,显示”没有匹配的员工”;④ 点”提交一条数据”,结果区显示 提交结果:success;⑤ 拔网线/改成错的地址再点查询,显示”加载失败:…”而不是白屏。
说明:这个练习故意没用 Vue——把 16 篇的 DOM 操作和这一篇的 Axios 合起来练一遍。等下一章用 Vue 写同样的东西,你会发现”渲染列表”和”更新提示文字”都不用手动操作 DOM 了。
如果你喜欢,那么欢迎来到我的世界!
了解更多暂未播放



"所有的相遇都是久别重逢。"—— 未知


