Ajax-概念、Http协议、Ajax请求及其常见问题
Ajax
- Ajax概念
- Ajax优缺点
- HTTP协议
- 请求报文
- 响应报文
- Ajax案例准备工作
- express基本使用
- 创建一个服务器
- 发送AJAX请求
- GET请求
- POST请求
- JSON响应
- Ajax请求出现的问题
- IE缓存问题
- Ajax请求超时与网络异常处理
- Ajax手动取消请求
- Ajax重复发送请求问题
Ajax概念
AJAX 全称为Asynchronous Javascript And XML,就是异步的JS和XML。通过AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。
XML:可扩展标记语言。XML被设计用来传输和存储数据。XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全部都是自定义标签,用来表示一些数据。(目前已经被JSON取代)
Ajax优缺点
优点:
- 可以无需刷新页面而与服务器端进行通信。
- 允许你根据用户事件来更新部分页面内容。
缺点:
- 没有浏览历史,不能回退。
- 存在跨域问题(同源)。
- SEO不友好(查看源代码中无法查找到)。
HTTP协议
HTTP全称为hypertext transport protocol 协议(超文本传输协议),协议详细规定了浏览器和万维网服务器之间互相通信的规则。
请求报文
请求行:POST
/URL
HTTP协议版本
请求头:
Host:值
Cookie: 值
Content-type:值
User-Agent:值
等等
空行:
请求体:如果是GET请求体为空,如果是POST可以不为空
响应报文
响应行:HTTP协议版本
响应状态码
响应状态字符串
响应头:
Content-type:值
Content-length:值
Content-encoding:值
等等
空行:
响应体:HTML语法内容
Ajax案例准备工作
express基本使用
先下载node并配置node环境,然后在vscode终端中输入npm i express
即可,若出现错误,可以尝试用管理员运行vscode再试一次,还是不行的话就找到node文件夹位置找到node_cache
node_global
node_modules
分别把这三个文件–>属性–>安全–>把权限改为完全控制。
此处可以安装到全局,也就是node.js根目录里npm i express -g
创建一个服务器
在当前目录新建个js文件(不一定非要在express安装的根目录里),然后在终端 --> 当前目录下 --> 输入node 文件名
就可以启动服务
-
可以使用nodemon实现保存自动重启
安装nodemon:
npm install -g nodemon
使用:在当前目录终端输入
nodemon 文件名
这样就不用每次修改都要重启服务了
注意:如果报错则输入
npx nodemon 文件名
再试一次
发送AJAX请求
GET请求
点击按钮div中呈现响应体:点击按钮发送AJAX请求给服务器,然后把响应体拿过来放到div中。
<!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>#result {width: 200px;height: 100px;border: solid 1px pink;}</style></head><body><button>点击发送请求</button><div id="result"></div><script>//获取button元素const btn = document.querySelector("button");const result = document.querySelector("#result");btn.addEventListener("click", function () {//1.创建对象const xhr = new XMLHttpRequest();//2.初始化,设置请求的方法和urlxhr.open("GET", "http://127.0.0.1:8000/server?a=1&b=2&c=3");//3.发送xhr.send();//4.事件绑定,处理服务端返回的结果//on 当……的时候//readyState是xhr对象中的属性,表示状态0 1 2 3 4//其中0-未初始化 1-open调用完毕 2-send调用完毕 3-服务端返回了部分结果 4-服务端返回了所有结果//change 改变xhr.onreadystatechange = function () {//判断服务端是否返回了所有结果if (xhr.readyState === 4) {//判断响应状态码 200 404 403 401 500// 2xx ,2开头都表示成功if (xhr.status >= 200 && xhr.status < 300) {//如果响应成功处理结果 行 头 空行 体console.log("状态码:", xhr.status); //状态码console.log("状态字符串:", xhr.statusText); //状态字符串console.log("响应头:", xhr.getAllResponseHeaders()); //所有的响应头console.log("响应体:", xhr.response); //响应体//设置result文本result.innerHTML = xhr.response;}}};});</script></body>
</html>
设置url参数:用?隔开,=赋值,&分隔
例如:http://127.0.0.1:8000/server?a=1&b=2&c=3
服务端server.js文件:
//1、引入express
const express = require('express');//2、创建应用对象
const app = express();//3、创建路由规则
//request是对请求报文的封装
//response是对响应报文的封装
app.get('/server',(request,response)=>{//设置响应头 设置允许跨域response.setHeader('Access-Controll-Allow-Origin','*');//设置响应response.send('HELLO AJAX');
});//4、监听端口启动服务
app.listen(8000,()=>{console.log("服务已经启动,8000端口监听中");
})
POST请求
鼠标经过div发送AJAX请求,然后拿回来响应体放在div中。
<!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>#result {width: 200px;height: 100px;border: solid 1px pink;}</style></head><body><div id="result"></div><script>const result = document.querySelector("#result");result.addEventListener("mouseover", function () {//1.创建对象const xhr = new XMLHttpRequest();//2.初始化 设置类型与urlxhr.open("POST", "http://127.0.0.1:8000/server");//设置请求头:固定写法,第一个参数设置请求体内容类型,第二个参数是参数查询字符串的类型xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");//3.发送请求,在这里传参,任意类型都可以xhr.send("a=1&b=2&c=3");// xhr.send('a:1&b:2&c:3');// xhr.send('1232142412421312');//4.绑定事件xhr.onreadystatechange = function () {//判断服务端是否返回所有结果if (xhr.readyState === 4) {//判断响应是否成功if (xhr.status >= 200 && xhr.status < 300) {//处理服务端返回的结果result.innerHTML = xhr.response;}}};});</script></body>
</html>
server.js:
//1、引入express
const express = require("express");//2、创建应用对象
const app = express();//3、创建路由规则
//request是对请求报文的封装
//response是对响应报文的封装
//GET请求
app.get("/server", (request, response) => {//设置响应头 设置允许跨域response.setHeader("Access-Controll-Allow-Origin", "*");//设置响应response.send("HELLO AJAX");
});//POST请求
app.post("/server", (request, response) => {//设置响应头 设置允许跨域response.setHeader("Access-Controll-Allow-Origin", "*");//设置响应response.send("HELLO AJAX POST");
});//4、监听端口启动服务
app.listen(8000, () => {console.log("服务已经启动,8000端口监听中");
});
JSON响应
服务端响应体也可以设置为一个数据发送过去,但是不能直接写,要通过JSON.stringify(数据)
把数据转换为JSON字符串
//可以接收任意类型的请求
app.all("/json-server", (request, response) => {//设置响应头 设置允许跨域response.setHeader("Access-Control-Allow-Origin", "*");response.setHeader("Access-Control-Allow-Headers", "*");//响应一个数据const data = {name: "haha",};//对对象进行字符串转换let str = JSON.stringify(data);//设置响应体response.send(str);
});
页面在拿到JSON字符串响应体的时候,是无法识别的,所以需要把JSON字符串转换为js对象,有两种方式:
- 手动转换
JSON.parse(xhr.response)
- 自动转换
xhr.responseType = 'json';
<!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>#result {width: 200px;height: 100px;border: solid 1px pink;}</style></head><body><div id="result"></div><script>const result = document.querySelector("#result");window.onkeydown = () => {const xhr = new XMLHttpRequest();//设置响应体数据类型xhr.responseType = "json";xhr.open("GET", "http://127.0.0.1:8000/json-server");xhr.send();xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) {//result.innerHTML = xhr.response;//手动对数据进行转换//let data = JSON.parse(xhr.response);//console.log(data);// result.innerHTML = data.name;//自动转换console.log(xhr.response);result.innerHTML = xhr.response.name;}}};};</script></body>
</html>
Ajax请求出现的问题
IE缓存问题
//针对IE缓存
app.get("/ie", (request, response) => {//设置响应头 设置允许跨域response.setHeader("Access-Control-Allow-Origin", "*");//设置响应response.send("HELLO IEhhh");
});
IE当你响应体改变时,它不会更新,而是缓存,要解决这个问题,就要让每次请求的url都不一样,那么我们在后面传个参数,值为时间戳(因为时间戳是不可能重复的,这样的话浏览器会认为url不一样就会重新发请求从而解决了问题),就可以解决改变响应体时IE走缓存不更新的问题。
xhr.open("GET", "http://127.0.0.1:8000/ie?t=" + Date.now());
Ajax请求超时与网络异常处理
我们不能保证服务端可以及时快速的响应,此时我们可以给Ajax做一个超时的设置然后给用户返回一个提醒,网络异常时也可返回一个提醒,提高用户体验感。
服务端写个定时器,2秒后发送响应体过去
//延时响应
app.get("/delay", (request, response) => {//设置响应头 设置允许跨域response.setHeader("Access-Control-Allow-Origin", "*");//设置响应//服务端写个定时器,2秒后发送响应体过去setTimeout(() => {response.send("HELLO 延时响应");}, 2000);
});
然后点击按钮发送请求时,可以设置超时xhr.timeout
和超时回调xhr.ontimeout
,还有网络异常回调xhr.onerror
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>IE缓存问题</title><style>#result {width: 200px;height: 100px;border: solid 1px pink;}</style></head><body><button>点击发送请求</button><div id="result"></div><script>const btn = document.querySelector("button");const result = document.querySelector("#result");btn.addEventListener("click", () => {const xhr = new XMLHttpRequest();//超时设置 2sxhr.timeout = 2000;//超时回调xhr.ontimeout = function () {alert("网络异常,请稍后重试!");};//网络异常回调xhr.onerror = function () {alert("你的网络似乎出了一些问题!请检查后重试!");};xhr.open("GET", "http://127.0.0.1:8000/delay");xhr.send();xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) {result.innerHTML = xhr.response;}}};});</script></body>
</html>
Ajax手动取消请求
在发送请求后还没得到响应时,可以手动取消请求,被取消时可返回一个提醒。
设置一个定时器发送响应体:
app.get('/cancel', (request, response) => {//设置响应头response.setHeader('Access-Control-Allow-Origin', '*');//设置响应体setTimeout(() => {!response.send('HELLO 请求已经被取消');}, 2000);
})
取消请求,用xhr.abort()
方法,abort=中止。
这里有个作用域的问题,解决方法是把xhr定义在外面给个null,然后赋值xhr实例,再调用方法。(重复赋值不能const)
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>手动取消请求</title></head><body><button>点击发送请求</button><button>点击取消请求</button><div id="result"></div><script>const send = document.querySelectorAll("button")[0];const cancel = document.querySelectorAll("button")[1];let xhr = null;//发送请求send.onclick = function () {xhr = new XMLHttpRequest();xhr.open("GET", "http://127.0.0.1:8000/cancel");xhr.send();};//取消请求,abort方法cancel.addEventListener("click", function () {xhr.abort(); //先点send再点cancel不会报错,先点cancel报错});</script></body>
</html>
Ajax重复发送请求问题
当用户狂点一个按钮时,浏览器会重复发送相同的请求,导致服务器压力过大。解决方法:当用户发请求时,先检查之前有没有相同的请求,如果已有,就把之前的请求取消掉,只响应最后一个请求(这里有防抖的思想,复习防抖节流点击此处)
<script>const btn = document.querySelector("button");let xhr = null;//标识变量 是否正在发送请求let isSending = false;//发送请求btn.onclick = function () {//判断标识变量if (isSending) x.abort();xhr = new XMLHttpRequest();//修改标识变量的值isSending = true;xhr.open("GET", "http://127.0.0.1:8000/delay");xhr.send();xhr.onreadystatechange = function () {if (xhr.readyState === 4) {isSending = false;}};};
</script>
相关文章:

Ajax-概念、Http协议、Ajax请求及其常见问题
Ajax Ajax概念Ajax优缺点HTTP协议请求报文响应报文 Ajax案例准备工作express基本使用创建一个服务器 发送AJAX请求GET请求POST请求JSON响应 Ajax请求出现的问题IE缓存问题Ajax请求超时与网络异常处理Ajax手动取消请求Ajax重复发送请求问题 Ajax概念 AJAX 全称为Asynchronous J…...

react 09之状态管理工具1 redux+ react-thunk的使用实现跨组件状态管理与异步操作
目录 react 09之状态管理工具1 redux react-thunk的使用实现跨组件状态管理与异步操作store / index.js store的入口文件index.js 在项目入口文件 引入store / actionType.js 定义action的唯一标识store / reducers / index.jsstore / actions / form.jsstore / reducers / for…...

opencv实战项目 手势识别-实现尺寸缩放效果
手势识别系列文章目录 手势识别是一种人机交互技术,通过识别人的手势动作,从而实现对计算机、智能手机、智能电视等设备的操作和控制。 1. opencv实现手部追踪(定位手部关键点) 2.opencv实战项目 实现手势跟踪并返回位置信息&…...
Netty对HPACK头部压缩的支持
前言 HTTP2终于支持对头部进行压缩传输了,Netty很早就支持HTTP2了,看下Netty对HPACK的实现源码,可以对HPACK理解的更深一下。 HpackDecoder Netty内置的编解码器Http2FrameCodec专门用来对HTTP2的各种Frame进行编解码,其中就包…...
C++:替换string中的字符
1.按照位置进行替换 string的成员函数replace可以满足这种需求,其变体有很多种,请参考官方文档,以下列举常用的两种: #include <iostream> #include <string> using namespace std;int main() {string s = "hello world";s.replace(s.begin(), s.b…...

【ChatGPT】自我救赎
ChatGPT辅助学习C之【在C中如果大数据类型转小数据类型会发生什么呢?】,今天问ChatGPT一个问题,让它解析下面这个C程序: #include <iostream> #include <cstdio> using namespace std; int main() {int a;long long b532165478…...

微信小程序(由浅到深)
文章目录 一. 项目基本配置1. 项目组成2. 常见的配置文件解析3. app.json全局的五大配置4.单个页面中的page配置5. App函数6.tabBar配置 二. 基本语法,事件,单位1. 语法2. 事件3. 单位 三. 数据响应式修改四 . 内置组件1. button2. image3. input4. 组件…...

冒泡排序 简单选择排序 插入排序 快速排序
bubblesort 两个for循环,从最右端开始一个一个逐渐有序 #include <stdio.h> #include <string.h> #include <stdlib.h>void bubble(int *arr, int len); int main(int argc, char *argv[]) {int arr[] {1, 2, 3, 4, 5, 6, 7};int len sizeof(…...

linux文件I/O之 open() 函数用法
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> typedef unsigned int mode_t ; int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); 函数功能 打开或创建一个文件 返回值 成功…...
用Java操作MySQL数据库
新建Maven项目 创建Maven项目 添加依赖 在pom.xml的标签里加上下面的内容 如果是MySQL 5.8那么的版本号是5.x.x, 例如5.1.49 如果是MySQL 8.0那么的版本号是8.x.x, 例如 8.0.28 <dependencies><!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java …...

SpringBoot启动报错:java: 无法访问org.springframework.boot.SpringApplication
报错原因:jdk 1.8版本与SpringBoot 3.1.2版本不匹配 解决方案:将SpringBoot版本降到2系列版本(例如2.5.4)。如下图: 修改版本后切记刷新Meavn依赖 然后重新启动即可成功。如下图:...
Vue3 setup语法糖 解决富文本编辑器上传图片64位码过长问题 quill-image-extend-module
引言: 富文本编辑器传图片会解码成64位,非常长导致数据库会报错第一种方法:将数据库类型改成 mediumtext第二种办法:本文中的方法 说明,本周文所用语法糖为Vue3 setup语法,即<script setup> 思路 拦…...
百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换
<!DOCTYPE html> <html><head><meta charset="UTF-8"><title></title></head><body><script>/*** * 百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换*///定义一些常量var x_PI = …...

论文浅尝 | CI4MRC:基于因果推断去除机器阅读理解中的名字偏差
笔记整理:朱珈徵,天津大学硕士,研究方向:问答 链接:https://aclanthology.org/2023.findings-acl.812/ 动机 机器阅读理解(Machine Reading Comprehension,MRC)是根据给定的文章回答…...

【校招VIP】测试计划之黑盒测试白盒测试
考点介绍: 黑盒测试&白盒测试是大厂和三四线公司校招的必考点。黑盒是以结果说话,白盒往往需要理解实现逻辑。现在商业项目的接口测试往往以白盒为主,也就是需要测试同学自己观察和修改数据库的值进行用例的测试。 但是无论采用哪种测试方…...

学习笔记整理-JS-01-语法与变量
文章目录 一、语法与变量1. 初识JavaScript2. JavaScript的历史3. JavaScript与ECMAScript的关系4. JavaScript的体系5. JavaScript的语言风格和特性 二、语法1. JavaScript的书写位置2. 认识输出语句3. REPL环境,交互式解析器4. 变量是什么5. 重点内容 一、语法与变…...
PHP之PHPExcel
include PHPExcel.php; include PHPExcel/Writer/Excel2007.php; //或者include PHPExcel/Writer/Excel5.php; 用于输出.xls的 //创建一个excel $objPHPExcel new PHPExcel(); // 输出Excel表格到浏览器下载 header(Content-Type: application/vnd.ms-excel); header(Content-…...

Redis系列(一):深入了解Redis数据类型和底层数据结构
Redis有以下几种常用的数据类型: redis数据是如何组织的 为了实现从键到值的快速访问,Redis 使用了一个哈希表来保存所有键值对。 Redis全局哈希表(Global Hash Table)是指在Redis数据库内部用于存储所有键值对的主要数据结构。…...
javaScript:如何获取html中的元素对象
目录 前言: 方法 1.通过id获取元素 2.通过标签名获取元素 3.通过类名class获取元素 获取body的方法 1.document.getElementsByTagName(body)[0] 2.document.body 相关代码 前言: 通过获取HTML中的元素对象,JavaScript可以对网页进行动…...

面试总结-webpack/git
说说你对webpack的理解 webpack 是一个静态模块打包器,整个打包过程就像是一条生产线,把资源从入口放进去,经过一系列的加工(loader),最终转换成我们想要的结果,整个加工过程还会有监控&#x…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...