AJAX 03 XMLHttpRequest、Promise、封装简易版 axios
AJAX 学习
- AJAX 3 原理
- 01 XMLHttpRequest
- ① XHR 定义
- ② XHR & axios 关系
- ③ 使用 XHR
- ④ XHR查询参数
- 案例:地区查询(URLSearchParams)
- ⑤ XHR数据提交 POST
- 02 Promise
- Promise 使用
- Promise - 三种状态
- 案例:使用Promise + XHR 获取省份列表
- 03 封装简易版 axios
- 完善1 myAxios-支持传递查询参数
- 完善2 myAxios-支持传递请求体数据
- 04 案例 - 天气预报
AJAX 3 原理
01 XMLHttpRequest
① XHR 定义

② XHR & axios 关系
axios 内部采用 XMLHttpRequest 与服务器交互

学习XHR的好处:掌握使用 XHR 与服务器进行数据交互,了解 axios 内部原理
③ 使用 XHR
步骤:
- 创建 XMLHttpRequest 对象
- 配置请求方法和请求 url 地址
- 监听 loadend 事件,接收响应结果
- 发起请求

举例:
在axios中,会自动把提交/返回的 JSON 字符串转变为数组,但是原生的 XMLHttpRequest 不会。
// 1. 创建 XMLHttpRequest 对象const xhr = new XMLHttpRequest()// 2. 配置请求方法和请求 url 地址xhr.open('GET','http://hmajax.itheima.net/api/province')// 3. 监听 loadend 事件,接收响应结果// loadend :请求和相应都完成了,就会触发这个回调函数xhr.addEventListener('loadend', () => {console.log(xhr.response);const data = JSON.parse(xhr.response)console.log(data);})// 4. 发起请求xhr.send()
1. AJAX 原理是什么?
➢ XMLHttpRequest 对象
2. 为什么学习 XHR?
➢ 有更多与服务器数据通信方式
➢ 了解 axios 内部原理
3. XHR 使用步骤?
➢ 创建 XHR 对象
➢ 调用 open 方法,设置 url 和请求方法
➢ 监听 loadend 事件,接收结果
➢ 调用 send 方法,发起请求
④ XHR查询参数
定义:浏览器提供给服务器的额外信息,让服务器返回浏览器想要的数据
语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2

区别axios,axios中有一个params的参数,会自动把里面的参数 拼接到url中,但是XHR中没有,我们可以利用 URLSearchParams
举例:
const xhr = new XMLHttpRequest()xhr.open('GET','http://hmajax.itheima.net/api/city?pname=辽宁省')xhr.addEventListener('loadend', () => {console.log(xhr.response);const text = document.querySelector('.text')text.innerHTML = JSON.parse(xhr.response).list.join('<br>')})xhr.send()
案例:地区查询(URLSearchParams)
需求:输入省份和城市名字,查询地区列表
请求地址:http://hmajax.itheima.net/api/area?参数名1=值1&参数名2=值2
- 注意上面的参数名 是后端规定的
在表单中输入省份、城市的名字,获取对象。我们要传递两个参数到服务器,传递多个参数的语法如上。不过这里是需要在表单中获取。可以自己定义一个对象,然后转换成参数名1=值1&参数名2=值2这样的格式,不过可以借助插件。

/*** 目标: 根据省份和城市名字, 查询对应的地区列表*/// 1. 查询按钮-点击事件document.querySelector('.sel-btn').addEventListener('click', () => {// 2. 收集省份和城市名字const pname = document.querySelector('.province').valueconst cname = document.querySelector('.city').value// 3. 组织查询参数字符串const qObj = {pname,cname}// 查询参数对象 -> 查询参数字符串const paramsObj = new URLSearchParams(qObj)const queryString = paramsObj.toString()console.log(queryString)// 4. 使用XHR对象,查询地区列表const xhr = new XMLHttpRequest()xhr.open('GET', `http://hmajax.itheima.net/api/area?${queryString}`)xhr.addEventListener('loadend', () => {console.log(xhr.response)const data = JSON.parse(xhr.response)console.log(data)const htmlStr = data.list.map(areaName => {return `<li class="list-group-item">${areaName}</li>`}).join('')console.log(htmlStr)document.querySelector('.list-group').innerHTML = htmlStr})xhr.send()})
⑤ XHR数据提交 POST
以注册账号为例。
需求:通过 XHR 提交用户名和密码,完成注册功能
核心:
请求头设置 Content-Type:application/json
请求体携带 JSON 字符串
注意:请求体Body参数对应axios中的data属性

案例:
<body><button class="reg-btn">注册</button>
</body>
<script>/*** 目标:使用XHR进行数据提交-完成注册功能*/// 点击注册按钮之后触发注册时间document.querySelector('.reg-btn').addEventListener('click',() => {// 假数据const newObj = {username: '11111111',password: '11111111'}// 1. 创建 XMLHttpRequest 对象const xhr = new XMLHttpRequest()// 2. 配置请求方法和请求 url 地址xhr.open('POST', 'http://hmajax.itheima.net/api/register')// 3. 监听 loadend 事件,接收响应结果// loadend :请求和相应都完成了,就会触发这个回调函数xhr.addEventListener('loadend', () => {console.log(xhr.response);})// 设置请求头 xhr.setRequestHeader('Content-Type','application/json')const usrStr = JSON.stringify(newObj)// 4. 发起请求xhr.send(usrStr)})
</script>
02 Promise
Promise 使用
Promise对象用于表示一个异步操作的最终完成(或失败)及其结果值。
学过的异步代码: setTimeout、 setInterval、AJAX
使用Promise管理异步任务
好处:
- 逻辑更清晰
- 了解 axios 函数内部运作机制
- 能解决回调函数地狱问题
语法:

注意 : catch中打印error,不能用 console.log(error) ,而是要用 console.dir(error)
案例:
// 目标:使用Promise管理异步任务// 1 创建Promis对象const p = new Promise((resolve,reject) => {// 2 执行异步代码setTimeout(()=> {// resolve('模拟AJAX请求-成功结果')reject(new Error('模拟AJAX请求-失败结果'))}, 2000)})// 3 获取结果p.then(result => {console.log(result);}).catch(error => {console.log(error);})
1. 什么是 Promise?
➢ 表示(管理)一个异步操作最终状态和结果值的对象
2. 为什么学习 Promise?
➢ 成功和失败状态,可以关联对应处理程序
➢ 了解 axios 内部原理(知道了axios的then和catch是怎么来的了)
3. Promise 使用步骤?
Promise - 三种状态
作用:了解Promise对象如何关联地处理函数,以及代码执行顺序
概念:一个Promise对象,必然处于以下几种状态之一
✓ 待定(pending) :初始状态,既没有被兑现,也没有被拒绝
✓ 已兑现(fulfilled) :意味着,操作成功完成
✓ 已拒绝(rejected) :意味着,操作失败
注意:Promise对象一旦被兑现/拒绝就是已敲定了,状态无法再被改变

// 创建Promis对象 pending 待定状态const p = new Promise((resolve,reject) => {// Promis对象 创建时,这里的代码都会执行了setTimeout(()=> {// resolve() => 'fullfilled状态-已兑现' => then()// resolve('模拟AJAX请求-成功结果')// reject() => 'rejected状态-已拒绝' => catch()reject(new Error('模拟AJAX请求-失败结果'))}, 2000)})console.log(p); // pending 待定状态// 3 获取结果p.then(result => {console.log(result);}).catch(error => {console.log(error);})
总结:
1. Promise 对象有哪 3 种状态?
➢ 待定 pending
➢ 已兑现 fulfilled
➢ 已拒绝 rejected
2. Promise 状态有什么用?
➢ 状态改变后,调用关联的处理函数
案例:使用Promise + XHR 获取省份列表
需求:使用 Promise 管理 XHR 获取省份列表,并展示到页面上
步骤:
- 创建 Promise 对象
- 执行 XHR 异步代码,获取省份列表
- 关联成功或失败函数,做后续处理
<body><p class="my-p"></p>
</body><script>const p = new Promise((resolve,reject) => {const xhr = new XMLHttpRequest()xhr.open('GET','http://hmajax.itheima.net/api/province11')xhr.addEventListener('loadend', () => {console.log(xhr);// console.log(xhr.response);// 怎么把 XHR 和 Promise 联系起来// 利用响应状态码if(xhr.status >= 200 && xhr.status < 300) {resolve(xhr.response)} else {reject(new Error(xhr.response))}})xhr.send()})p.then(result => {console.log(result);const myP = document.querySelector('.my-p')myP.innerHTML = JSON.parse(result).list.join('<br>')}).catch(error => {console.dir(error)const myP = document.querySelector('.my-p')myP.innerHTML = error.message})
</script>
03 封装简易版 axios
需求:基于 Promise + XHR 封装 myAxios 函数,获取省份列表展示
步骤:
-
定义 myAxios 函数,接收配置对象,返回 Promise 对象
为什么要有配置对象:调用axios的时候,传进了url、params、data配置对象。为什么要返回Promise对象,因为我们在使用axios后,还可以使用 then catch。
-
发起 XHR 请求,默认请求方法为 GET
-
调用成功/失败的处理程序
-
使用 myAxios 函数,获取省份列表展示

<body><p class="myp"></p>
</body>
<script>// 需求:基于 Promise + XHR 封装 myAxios 函数,获取省份列表展示function myAxios(config) { // config是一个对象!return new Promise((resolve, reject) => {// 发起XHR请求 默认请求方法为GETconst xhr = new XMLHttpRequest()xhr.open(config.method || 'GET', config.url)xhr.addEventListener('loadend', ()=>{if(xhr.status >= 200 && xhr.status < 300) {// 这里要模仿axios,axios是自动转换JSON字符的resolve(JSON.parse(xhr.response))} else {reject(new Error(xhr.response))}})xhr.send()})}myAxios({url: 'http://hmajax.itheima.net/api/province'}).then(result => {console.log(result);const myp = document.querySelector('.myp')myp.innerHTML = result.list.join('<br>')}).catch(error => {console.log(error);const myp = document.querySelector('.myp')myp.innerHTML = error.message})
</script>
完善1 myAxios-支持传递查询参数
需求:修改 myAxios 函数支持传递查询参数,获取"辽宁省","大连市"对应地区列表展示
步骤:
- myAxios 函数调用后,判断 params 选项
- 基于 URLSearchParams 转换查询参数字符串
- 使用自己封装的 myAxios 函数展示地区列表
// 需求:修改 myAxios 函数支持传递查询参数,获取"辽宁省","大连市"对应地区列表展示function myAxios(config) { return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest()// 1 判断有params选项,携带查询参数if(config.params) {// 2 使用 URLSearchParams 转换,并携带url上const paramsObj = new URLSearchParams(config.params)const queryString = paramsObj.toString()// 把查询参数字符串,拼接在url ? 后面config.url += `?${queryString}`}xhr.open(config.method || 'GET', config.url)xhr.addEventListener('loadend', ()=>{if(xhr.status >= 200 && xhr.status < 300) {resolve(JSON.parse(xhr.response))} else {reject(new Error(xhr.response))}})xhr.send()})}
完善2 myAxios-支持传递请求体数据
需求:修改 myAxios 函数支持传递请求体数据,完成注册用户功能
步骤:
- myAxios 函数调用后,判断 data 选项
- 转换数据类型,在 send 方法中发送
- 使用自己封装的 myAxios 函数完成注册用户功能

function myAxios(config) { return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest()if(config.params) {const paramsObj = new URLSearchParams(config.params)const queryString = paramsObj.toString()config.url += `?${queryString}`}xhr.open(config.method || 'GET', config.url)xhr.addEventListener('loadend', ()=>{if(xhr.status >= 200 && xhr.status < 300) {resolve(JSON.parse(xhr.response))} else {reject(new Error(xhr.response))}})// 1 判断有data选项,携带请求体if(config.data) {// 接口文档规定接受的字符是JSONconst jsonStr = JSON.stringify(config.data)// 请求头xhr.setRequestHeader('Content-Type','application/json')xhr.send(jsonStr)} else {xhr.send()}})}
04 案例 - 天气预报
BV1MN411y7——P43
相关文章:
AJAX 03 XMLHttpRequest、Promise、封装简易版 axios
AJAX 学习 AJAX 3 原理01 XMLHttpRequest① XHR 定义② XHR & axios 关系③ 使用 XHR④ XHR查询参数案例:地区查询(URLSearchParams)⑤ XHR数据提交 POST 02 PromisePromise 使用Promise - 三种状态案例:使用Promise XHR 获取…...
如何将办公资料文件生成二维码?扫码可看详情
日常办公的时候,经常会需要应用二维码来向同事或者客户发送和展示一些资料。比如包含企业介绍和产品介绍的资料、一些操作流程的资料、产品展示宣传视频、活动安排详情、比赛流程、会议资料… 这些都能通过一个文件二维码来展示。 文件二维码支持将PDF文件生成二维…...
【Streamlit学习笔记】实现包含多个sheet的excel文件下载
1、什么是Streamlit Streamlit是一个免费的开源框架,用于快速构建和共享漂亮的机器学习和数据科学Web应用程序,官网链接 Streamlit Streamlit API链接 API reference 实际项目中遇到的问题:包含多个sheet的excel文件下载,下面将给…...
[Redis]——主从同步原理(全量同步、增量同步)
目录 Redis集群: 主从同步原理: replid和offset: 全量同步和增量同步: repl_baklog文件: 主从集群的优化: Redis集群: 部署多台Redis我们称之为Redis集群,他有一个主节点(负责写操作)&…...
Buildroot 之二 详解构建架构、流程、external tree、示例
构建系统 Buildroot 中的构建系统使用的是从 Linux Kernel(4.17-rc2) 中移植的 Kconfig(配置) + Makefile & Kbuild(编译)这套构建系统,移植后的源码位于 support/kconfig/ 目录下。Buildroot 本身是一个构建系统,与直接编译源码不同,因此,它对这套系统进行了比较…...
牛客小白月赛61-C-小喵觅食
很经典的bfs,就是从猫咪和MM的坐标开始bfs搜索 不过这题有些小细节需要注意 1.认真审题,注意,猫一旦闻到小鱼干的味道,开始动,此时MM就不动了,一开始没仔细审题,很不好的习惯 2.注意移动的条件,vis,不是墙,距离是MM的移动距离范围内 3.这个猫咪的r2是闻味道的r2,不是移动距…...
200 名专家编写报告:AI 发展可能对人类构成「灭绝级威胁」
3 月 14 日消息,美国国务院委托编写了一份新报告,警告 AI 正呈指数级发展,可能会对人类构成「灭绝级威胁」。 这份报告全称为《提高先进人工智能安全保障的行动计划》,要求美国政府必须迅速、果断地采取行动,以避免 A…...
学习Android的第二十九天
目录 Android Service 与 Activity 通讯 范例 Android Service Alarm 定时广播 Alarm Alarm 使用流程 范例 Android IBinder Binder 为什么是 Binder ? Android Service 与 Activity 通讯 Activity 与 Service 通信的媒介就是 Service 中的 onBind() 方法࿰…...
SpringMVC重点记录
目录 1.学习重点2.回顾MVC3.回顾servlet4.初始SpringMVC4.1.为什么要学SpringMVC?4.2.SpringMVC的中重点DispatcherServlet4.3.SpringMVC项目的搭建4.4.MVC框架要做哪些事情?4.5.可能会遇到的问题 5.SpringMVC的执行原理6.使用注解开发SpringMVC7.Controller控制总结8.RestF…...
一条 SQL 更新语句如何执行的
Server 层 存储引擎层 总流程 查询语句 连接器 查询缓存 分析器 优化器 执行器 更新语句 redo log(节省的是随机写磁盘的 IO 消耗(转成顺序写&#x…...
Github上哪些好用的安全工具1
专注于web漏洞挖掘、内网渗透、免杀和代码审计,感谢各位师傅的关注!网安之路漫长,与君共勉! URLFinder 一款快速提取网页信息的工具。该项目可以快速爬取网页上的 URL 地址、JS 文件里的 API 接口等信息,支持批量抓取…...
手写Mybatis自动填充插件
目录 一、Mybatis插件简介🥙二、工程创建及前期准备工作🥫实现代码配置文件 三、插件核心代码实现🍗四、测试🥓 一、Mybatis插件简介🥙 Mybatis插件运行原理及自定义插件_简述mybatis的插件运行原理,以及如何编写一个…...
upload文件上传漏洞复现
什么是文件上传漏洞: 文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。“…...
Docker 安装部署 SqlServer 数据库
Docker 安装部署 SqlServer 数据库 背景: 最近在开发数据中台数据集成模块,需要对接大量的数据做测试, 由于SqlServer 下载安装会耗费大量时间,所以采用 Docker 安装 Sqlserver 的方式部署数据库。 1、拉去 sqlserver 镜像 …...
cmath 中cos sin等常用函数的坑(弧度角度换算)
cmath中三角函数的输入是弧度,不是角度.忘了这件事,找bug找了好久! 弧度是旧称弪。在数学和物理中,弧度是角的度量单位。它是由国际单位制导出的单位,单位缩写是rad。弧度是指在一个圆中,弧长和半径之比,即|弧度|弧长半径。 角度…...
深度解析HTTP反向代理-okey proxy
反向代理這個概念可能並不常見,但其實它對於提升網路安全和訪問速度方面發揮著很大作用。 HTTP反向代理(HTTP Reverse Proxy)是一種特殊的代理伺服器,首先它能夠接收互聯網上的連接請求,然後將這些請求轉發給內部網路…...
SwinIR训练报错解决
swinir训练报错解决 记录swinir图像超分重建算法复现过程中的报错信息,并提供相应的解决方案 报错信息 UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at C:\actions-runner\_work\pyto…...
C++类和对象一
#include <iostream> using namespace std;//设计一个学生类 class CStudent {public: //公有成员void InputData(){cout << "请输入学号";cin >> sno;cout << "请输入姓名";cin >> sname;cout << "请输入分…...
Linux之线程互斥
目录 一、问题引入 二、线程互斥 1、相关概念 2、加锁保护 1、静态分配 2、动态分配 3、锁的原理 4、死锁 三、可重入与线程安全 1、概念 2、常见的线程不安全的情况 3、常见的线程安全的情况 4、常见不可重入的情况 5、常见可重入的情况 6、可重入与线程安全联系…...
C++ 拷贝构造函数和运算符重载
目录 一. 拷贝构造函数 1. 引入 2. 拷贝构造的概念 3. 浅拷贝 4. 深拷贝 二. C运算符重载 1. 概念 2. 注意事项 3.举例 一. 拷贝构造函数 1. 引入 我们在创建对象时,能不能创建一个与原先对象一模一样的新对象呢?为了解决这个问题&#x…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
