入门AJAX——XMLHttpRequest(Get)
一、什么是 AJAX
AJAX = Asynchronous JavaScript And XML(异步的 JavaScript 和 XML)。
1、XML与异步JS
XML: 是一种比较老的前后端数据传输格式(已经几乎被 JSON 代替)。它的格式与HTML类似,通过严格的闭合自定义标签实现对数据的解释。
异步JS: 所谓异步与同步相对。同步指的是当JS遇到耗时操作(网络请求)时原地等待操作完成而阻塞下面的代码。而异步JS在遇到耗时操作时会继续执行下面的代码,等响应返回后继续处理。
2、AJAX的特点
AJAX最大的优点就是可以在不重新加载这个页面的情况下,与服务器交换部分数据并且更新部分网页内容。
3、本文我们会做什么
实现AJAX的方法可以大概分为两种:XMLHttpRequest
和 fetch
,在本文,我们着重介绍前者。
既然是网络请求,就自然需要后端的支持。我们会首先搭建一个本地的后端服务器。前端小伙伴看到这可能不淡定了:
什么?让我去写后端,还是算了,告辞!
先别急着走嘛,当然啦,我这边已经把接口部署到服务器上了,大家如果嫌麻烦的话,下文中的所有 url 前缀请使用 http://39.105.227.198:1234
并跳过下文中的后端接口搭建内容。
完整代码在文章末尾(前端,使用在线接口)
4、前置知识
学习本文之前,请确保你已经了解了下面知识点的相关概念和基础用法:
- 基础的
dom
操作 网络的基本知识
(请求方法、请求传参、状态码等)- 了解在
浏览器中调试
的基本方法 - 有对公共代码进行
封装的意识
二、实现简单的 AJAX
1、基于express快速搭建后端接口
后端搭建不是本文重点,所以直接上代码,如果你使用的是服务器上的接口,可以跳过本节:
npm install express body-parser cookie-parser multer cors --save
根目录下新建 app.js
const express = require('express')
const cors = require('cors')
const app = express()app.use(cors())app.get('/test/1', (req, res) => {res.send('hello world')
})app.listen(1234, () => {console.log('服务器运行在 http://localhost:1234')
})
启动本服务器,我们将与 1234 端口交互:
node ./app.js
服务器运行在 http://localhost:1234
看到服务器运行在 http://localhost:1234
标标标明服务器启动成功。
2、前端请求
下面我们通过代码来认识如何去使用 XMLHttpRequest
发起AJAX请求:
// html 文件
<div id="app"></div><script>// 创建请求对象const xhr = new XMLHttpRequest() // 如果你使用的是我提供的服务器接口,请将 url 修改为:// http://39.105.227.198:1234/test/1const url = 'http://localhost:1234/test/1'// 配置:向 url 发起异步 GET 请求xhr.open('GET', url, true) xhr.onreadystatechange = function () {// 如果请求成功if (xhr.readyState === 4 && xhr.status === 200) {const res = xhr.responseText// 将 ID 为 app 的元素内文字改为响应的文字document.querySelector('#app').innerHTML = res}}// 发送请求xhr.send()
</script>
运行上面的 html 代码,你将在页面上看到后端返回的 hello world!
,并在调试台看到网页发送了一次 GET 请求。
恭喜你,已经成功发出了一个 AJAX 请求并收到返回的结果!
3、知识点讲解
现在回看我们的代码都干了什么:
首先我们创建了一个请求对象 xhr
:
const xhr = new XMLHttpRequest()
接下来我们对 AJAX 请求的控制本质上就是对这个 xhr 的控制。
然后我们对本次发送的请求进行配置:
// 如果你使用的是我提供的服务器接口,请将 url 修改为:
// http://39.105.227.198:1234/test/1
const url = 'http://39.105.227.198:1234/test/1'
// 配置:向 url 发起异步 GET 请求
xhr.open('GET', url, true)
xhr.open()
方法接收三个参数:method、url 和 isAsync
- method: 本次请求的方法,如 get、post等。
- url: 顾名思义,本次请求要发到哪里。
- isAsync: 自己起的名字,本次请求是否异步,我们建议使用异步。
在 xhr 对象上有一个属性 readyState
,该属性的取值范围是0~4
,用于跟踪请求的进度并处理响应。
状态码 | 常量 | 描述 |
---|---|---|
0 | UNSENT | XHR 对象已创建,但尚未调用 open() 方法。 |
1 | OPENED | 已调用 open() 方法,请求已初始化,但尚未发送(未调用 send())。 |
2 | HEADERS_RECEIVED | 已调用 send() 方法,服务器已接收请求并返回响应头。 |
3 | LOADING | 服务器正在返回响应体(数据正在传输中),responseText 已有部分数据。 |
4 | DONE | 请求已完成(成功或失败),响应数据已完全接收。 |
而onreadystatechange
是一个事件处理函数,当 XHR 的 readyState 状态发生变化时会触发该事件。开发者可以通过监听这个事件来跟踪请求的进度并处理响应。
xhr.onreadystatechange = function () {// 如果请求成功// status 是状态码,200 ~ 299 表示请求成功if (xhr.readyState === 4 && xhr.status === 200) {const res = xhr.responseText// 将 ID 为 app 的元素内文字改为响应的文字document.querySelector('#app').innerHTML = res}
}
所以上面代码的意思就是:当请求完成并且成功返回后,将 id 为 app 的元素内文字改为响应的结果(hello world)。然后我们使用 xhr.send()
发送请求。
三、实现一个简单的搜索词推荐功能
让我们实现一个简单的搜索词推荐功能:页面上有一个输入框,只能接收一个小写英文字母
,每次我们输入,都会主动向服务器发送当前输入框内的字母,然后服务器返回一个以这个字母开头的单词,前端将这个单词显示在页面上,如果没有匹配到任何一个单词,则返回 no suggest。
1、后端代码
如果你依旧使用我提供的接口,那么该节内容你依旧不需要阅读,记得请求时把 URL 改正确就行。
我们的代码基于之前的代码:
// app.js
const express = require('express')
const cors = require('cors')
const app = express()app.use(cors())app.get('/test/1', (req, res) => {res.send('hello world')
})
/* --------------添加代码-----------------*/
app.get('/test/2', (req, res) => {const char = req.query.charres.send(char2Word.get(char) || 'no suggest')
})const char2Word = new Map()char2Word.set('a', 'Anna')
char2Word.set('b', 'Brittany')
char2Word.set('c', 'Cinderella')
char2Word.set('d', 'Diana')
char2Word.set('e', 'Eva')
char2Word.set('f', 'Fiona')
char2Word.set('g', 'Gunda')
char2Word.set('h', 'Hege')
char2Word.set('i', 'Inga')
char2Word.set('j', 'Johanna')
char2Word.set('k', 'Kitty')
char2Word.set('l', 'Linda')
char2Word.set('m', 'Mom')
char2Word.set('n', 'No')
char2Word.set('o', 'Ok')
char2Word.set('p', 'Picture')
char2Word.set('q', 'Quick')
char2Word.set('r', 'Reset')
char2Word.set('s', 'String')
char2Word.set('t', 'TypeSrcipt')
char2Word.set('u', 'unit')
char2Word.set('v', 'Vicky')
char2Word.set('w', 'Wenche')
char2Word.set('x', 'x-rian')
char2Word.set('y', 'Yellow')
char2Word.set('z', 'Zoom')
/* --------------添加代码-----------------*/
app.listen(1234, () => {console.log('服务器运行在 http://localhost:1234')
})
2、前端代码
创建一个输入框和一个用于显示搜索结果的盒子:
<input id="charInput" placeholder="请输入一个小写字母" type="text"><div id="suggest">no suggest</div>
接下来,我们将请求进行简单的封装,以后我们想发起请求只需调用该函数:
function getRequest (url, callback) {const xhr = new XMLHttpRequest()xhr.open('GET', url, true)xhr.onreadystatechange = function () {if (xhr.readyState === 4 && xhr.status === 200) {const res = xhr.responseTextcallback(res)}}xhr.send()
}
然后给 input 输入框绑定输出事件回调,每次输入就调用getRequest
将出入的字母发送到后端,获取到结果后将其设置到下面的 div 中:
inputChange = (str) => {// 如果你使用的是我提供的服务器接口,请将 url 修改为:// http://39.105.227.198:1234/test/2?char=${str}getRequest(`http://localhost:1234/test/2?char=${str}`, (res) => {document.querySelector('#suggest').innerHTML = res})
}document.querySelector('#charInput')
.addEventListener('input', (e) => inputChange(e.target.value))
至此前端代码书写完毕,运行 html ,在输入框中输入一个小写字母,发现下面的建议文字会跟着变化,且建议文字的首字母就是你输入的字母:
四、请求的超时取消
很多时候我们希望当请求长时间没有响应时取消该请求,在XMLHttpRequest
中,我们使用 abort()
函数实现。
const xhr = new XMLHttpRequest()
// ... 代码
xhr.abort() // 取消请求
我们现在对上文中的 getRequest
函数进行以下扩展,使它支持超时取消:
// 添加超时事件和取消回调
function getRequest (url, callback, timeout = 5000, abortCallBack = () => {}) {const xhr = new XMLHttpRequest()setTimeout(() => {xhr.abort()abortCallBack()}, timeout)xhr.open('GET', url, true)xhr.onreadystatechange = function () {if (xhr.readyState === 4 && xhr.status === 200) {const res = xhr.responseTextcallback(res)}}xhr.send()
}
我们新建一个接口,让这个接口延迟3秒后返回结果。
然后布置两个盒子,其中一个设置为1秒超时,一个设置为5秒超时。
如果成功接收到接口的返回值,就将盒子的内容更改为该返回值,被取消请求的盒子内容改为:“我的请求被取消”。
让我们先预测一下,应该是第一个盒子的内容应该是“我的内容被取消”,因为它设置到超时时间短于结果的返回所需时间;而第二个盒子的内容可以被正常修改:
// app.js
.... 之前的代码
app.get('/test/3', (req, res) => {setTimeout(() => {res.send('成功返回')}, 3000) // 延迟三秒返回,使其中一个盒子请求被取消
})
// html
<div class="box" id="abortable1">我的请求1秒后被取消</div>
<div class="box" id="abortable2">我的请求5秒后被取消</div><script>
function getRequest (url, callback, timeout = 5000, abortCallBack = () => {}) {const xhr = new XMLHttpRequest()setTimeout(() => {xhr.abort()abortCallBack()}, timeout)xhr.open('GET', url, true)xhr.onreadystatechange = function () {if (xhr.readyState === 4 && xhr.status === 200) {const res = xhr.responseTextcallback(res)}}xhr.send()
}// 超时时间设置为 1 秒,该元素的请求将由于超时被取消
getRequest('http://39.105.227.198:1234/test/3', (res) => {document.querySelector('#abortable1').innerHTML = res
}, 1000, () => {document.querySelector('#abortable1').innerHTML = '我的请求被取消'
})// 超时事件为 5 秒,将被正常修改
getRequest('http://39.105.227.198:1234/test/3', (res) => {document.querySelector('#abortable2').innerHTML = res
})
</script>
运行结果如图:
可以看到第一个元素的请求由于超时被取消,第二个元素正确返回并修改了文字。
五、完整代码
以下代码集成了本文章的三个例子,并对请求进行了简单的封装,可以直接运行:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.box {background: pink;width: 300px;height: 30px;line-height: 30px;margin: 10px 0;}</style>
</head>
<body><div id="app"></div><input id="charInput" placeholder="请输入一个小写字母" type="text"><div id="suggest">no suggest</div><div class="box" id="abortable1">我的请求1秒后被取消</div><div class="box" id="abortable2">我的请求5秒后被取消</div><script>function getRequest (url, callback, timeout = 5000, abortCallBack = () => {}) {const xhr = new XMLHttpRequest()setTimeout(() => {xhr.abort()abortCallBack()}, timeout)xhr.open('GET', url, true)xhr.onreadystatechange = function () {if (xhr.readyState === 4 && xhr.status === 200) {const res = xhr.responseTextcallback(res)}}xhr.send()}inputChange = (str) => {getRequest(`http://39.105.227.198:1234/test/2?char=${str}`, (res) => {document.querySelector('#suggest').innerHTML = res})}document.querySelector('#charInput').addEventListener('input', (e) => inputChange(e.target.value))getRequest('http://39.105.227.198:1234/test/1', (res) => {document.querySelector('#app').innerHTML = res})getRequest('http://39.105.227.198:1234/test/3', (res) => {document.querySelector('#abortable1').innerHTML = res}, 1000, () => {document.querySelector('#abortable1').innerHTML = '我的请求被取消'})getRequest('http://39.105.227.198:1234/test/3', (res) => {document.querySelector('#abortable2').innerHTML = res})</script>
</body>
</html>
相关文章:

入门AJAX——XMLHttpRequest(Get)
一、什么是 AJAX AJAX Asynchronous JavaScript And XML(异步的 JavaScript 和 XML)。 1、XML与异步JS XML: 是一种比较老的前后端数据传输格式(已经几乎被 JSON 代替)。它的格式与HTML类似,通过严格的闭合自定义标…...

5分钟申请edu邮箱【方案本周有效】
这篇文章主要展示的是成果。如果你是第1次看见我的内容,具体的步骤请翻看往期的两篇作品。先看更正补全,再看下一个。 建议你边看边操作。 【更正补全】edu教育申请通过方案 本周 edu教育邮箱注册可行方案 #edu邮箱 伟大无需多言 我已经验证了四个了…...

闲谈PMIC和SBC
今天不卷,简单写点。 在ECU设计里,供电芯片选型是逃不开的话题,所以聊聊PMIC或者SBC的各自特点,小小总结下。 PMIC,全称Power Management Intergrated Circuits,听名字就很专业:电源管理&…...

Java垃圾回收机制深度解析:从理论到实践的全方位指南
Java垃圾回收(GC)是Java虚拟机(JVM)的核心功能,它自动管理内存分配与回收,避免了C/C中常见的内存泄漏问题。本文将深入剖析Java垃圾回收的工作原理、算法实现、收集器类型及调优策略,助你全面掌握JVM内存管理的精髓。 一、垃圾回收基础概念 …...
Ubuntu系统 | 本地部署ollama+deepseek
1、Ollama介绍 Ollama是由Llama开发团队推出的开源项目,旨在为用户提供高效、灵活的本地化大型语言模型(LLM)运行环境。作为Llama系列模型的重要配套工具,Ollama解决了传统云服务对计算资源和网络连接的依赖问题,让用户能够在个人电脑或私有服务器上部署和运行如Llama 3等…...

论文阅读:CLIP:Learning Transferable Visual Models From Natural Language Supervision
从自然语言监督中学习可迁移的视觉模型 虽然有点data/gpu is all you need的味道,但是整体实验和谈论丰富度上还是很多的,也是一篇让我多次想放弃的文章,因为真的是非常长的原文和超级多的实验讨论,隔着屏幕感受到了实验的工作量之…...

在图像分析算法部署中应对流行趋势的变化|文献速递-深度学习医疗AI最新文献
Title 题目 Navigating prevalence shifts in image analysis algorithm deployment 在图像分析算法部署中应对流行趋势的变化 01 文献速递介绍 机器学习(ML)已开始革新成像研究与实践的诸多领域。然而,医学图像分析领域存在显著的转化鸿…...

CAMEL-AI开源自动化任务执行助手OWL一键整合包下载
OWL 是由 CAMEL-AI 团队开发的开源多智能体协作框架,旨在通过动态智能体交互实现复杂任务的自动化处理,在 GAIA 基准测试中以 69.09 分位列开源框架榜首,被誉为“Manus 的开源平替”。我基于当前最新版本制作了免安装一键启动整合包。 CAMEL-…...
Selenium 中 JavaScript 点击的优势及使用场景
*在 Selenium 自动化测试中,使用 JavaScript 执行点击操作(如driver.execute_script("arguments[0].click();", element))相比直接调用element.click()有以下几个主要优势: 1. 绕过元素不可点击的限制 问题场景&#x…...

Linux系统-基本指令(5)
文章目录 mv 指令cat 指令(查看小文件)知识点(简单阐述日志)more 和 less 指令(查看大文件)head 和 tail 指令(跟查看文件有关)知识点(管道)时间相关的指令&a…...
C++ set数据插入、set数据查找、set数据删除、set数据统计、set排序规则、代码练习1、2
set数据插入,代码见下 #include<iostream> #include<set> #include<vector>using namespace std;void printSet(const set<int>& s) {for (set<int>::const_iterator it s.begin(); it ! s.end(); it) {cout << *it <…...
[android]MT6835 Android 指令启动MT6631 wifi操作说明
问题说明 MT6835使用指令启动wifi 使用andorid指令启动 2.4G启动方式 cmd wifi start-softap ctltest wpa2 11111111 -b 2 5G启动指令 cmd wifi start-softap ctltest wpa2 11111111 -b 5 使用linux指令启动 指令启动wifi 新建br-lan brctl addbr br-lan 关闭wifi a…...

C# winform教程(二)
一、基础控件 常用的基础控件主要有按钮,文本,文本输入,组,进度条,等等。 基础控件 名称含义详细用法Button按钮Buttoncheckbox多选按钮Combobox下拉选择groupbox组控件label标签,显示文字panel控件集合&a…...
Java详解LeetCode 热题 100(25):LeetCode 141. 环形链表(Linked List Cycle)详解
文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 环形链表的可视化2.2 核心难点 3. 解法一:HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二:快慢指针法(…...

【仿生机器人】刀剑神域计划——仿生机器人.亚丝娜
我在做仿生机器人头,硬件部分已经搭建完毕,包括头部和颈部,用的23个舵机驱动机器人做表情,也支持头部的旋转(就是颈部的功能),安装了摄像头在眼睛中,还有麦克风接受周围环境声音&…...

ARM架构推理Stable Diffusiond
代码仓库: https://github.com/siutin/stable-diffusion-webui-docker.git Docker容器地址: https://hub.docker.com/r/siutin/stable-diffusion-webui-docker/tags git clone https://github.com/siutin/stable-diffusion-webui-docker.git cd stabl…...

仓颉项目调试配置与多文件场景下的问题解析
1. 调试配置指南 在 VS Code 中配置好仓颉开发工具链后,只需按下 F5 或 Fn F5 即可启动调试。 在 CodeArts IDE for Cangjie 中,需先通过右上角的 编辑配置 -> 新增配置项 -> 选择 Cangjie (cjdb) Debug -> 选择 launch 模式 -> 点击 确认…...
Easyui悬停组件
文章目录 一、EasyUI 官方悬停解决方案:Tooltip 组件1. 基础用法2. 高级配置项 二、进阶场景:Datagrid 表格悬停扩展1. 监听行事件2. 第三方扩展包(流云大神版) 三、自定义悬停样式四、常见问题解决 在EasyUI中,没有直…...

MySQL 8.0 OCP 英文题库解析(十)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题81~90 试题81:…...

Python Pytest
1.Pytest用例发现规则 1.1 模块名(python文件)名必须以 test_ 开头或 _test 结尾,如 test_case,case_test,下划线都不能少 1.2 模块不能放在 . 开头的隐藏目录或者叫 venv的目录下,virtual environment,叫venv1都可以…...
金属膜电阻和碳膜电阻
1、性能比较 特性金属膜电阻对比碳膜电阻精度0.1% ~ 1%5% ~ 10%温度系数15 ~ 50 ppm/℃(极低漂移)200 ~ 1000 ppm/℃噪声0.1 μV/V 以下(超低噪声)1~5 μV/V(中高频噪声显著)高频特性寄生电感/电容小&…...
DNS (Domain Name System) 域名系统 将域名解析为 IP 地址
✅ DNS 服务器是指什么? **DNS 服务器(Domain Name System Server)是一个将域名(如 www.baidu.com)解析为 IP 地址(如 220.181.38.150)**的服务器。 🧠 一句话理解: DNS…...

如何轻松删除 Android 上的文件(3 种方法)
Android 手机是非常强大的设备,可让我们存储大量的个人数据,从照片和视频到应用程序和文档。然而,随着时间的推移,您的设备可能会因不再需要的文件而变得混乱。删除这些文件有助于释放空间并提高性能。在本指南中,我们…...

[特殊字符] Unity UI 性能优化终极指南 — ScrollRect篇
ScrollRect ManualScrollRect API 我参考了官方最新文档(基于UGUI 3.0包),加上实际性能测试经验,直接给你梳理: 🎯 Unity UI 性能优化终极指南 — ScrollRect篇 🧩 什么是 ScrollRectÿ…...

自适应流量调度用于遥操作:面向时间敏感网络的通信与控制协同优化框架
英文标题:Adaptive Flow Scheduling for Teleoperation: A Communication and Control Co-Optimization Framework over Time-Sensitive Networks 中文标题:自适应流量调度用于遥操作:面向时间敏感网络的通信与控制协同优化框架 作者信息 …...

阿里云服务器-解决宝塔登录不成功
出现问题: This site can’t be reached XX.XX.XXX.XXX took too long to respond. Try: Checking the connection Checking the proxy and the firewall Running Windows Network Diagnostics ERR_CONNECTION_TIMED_OUT 可能是端口未开放 原因:服务器…...
6.3 day 35
知识点回顾: 三种不同的模型可视化方法:推荐torchinfo打印summary权重分布可视化进度条功能:手动和自动写法,让打印结果更加美观推理的写法:评估模式 可视化 理解深度学习网络最重要的2点: 1.了解损失如何定…...

graphviz, dot, Error: lost rA sA edge; 独立的模块
1) 有向图dot文件 digraph R { node [shaperecord]; { ranksame rA sA tA } { ranksame uB vB wB } rA -> sA; sA -> vB; t -> rA; uB -> vB; wB -> u; wB -> tA; } 2)出现报警信息 Warning: flat edge between adjacent …...
MicroROS简述
文章目录 前言1. 什么是MicroROS2. MicroROS的功能2.1 Micro-ROS 的核心作用:桥梁 翻译官2.2 为什么服务端(Agent)能知道设备端的消息和服务? 3. MicroROS出现的背景3.1 机器人系统的“断层”问题3.2 物联网与边缘计算的兴起3.3 …...
LeetCode Hot100刷题——完全平方数
279. 完全平方数 给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。 完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而…...