第 2 章:AJAX 的使用

2024-09-06 04:52
文章标签 使用 ajax

本文主要是介绍第 2 章:AJAX 的使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

AJAX 的使用

核心对象:XMLHttpRequest,AJAX 的所有操作都是通过该对象进行的。

1. 使用步骤

  1. 创建 XMLHttpRequest 对象
    var xhr = new XMLHttpRequest();

  2. 设置请求信息

xhr.open(method, url);//可以设置请求头,一般不设置
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  1. 发送请求
    xhr.send(body) //get 请求不传 body 参数,只有 post 请求使用

  2. 接收响应

//xhr.responseXML 接收 xml 格式的响应数据
//xhr.responseText 接收文本格式的响应数据
xhr.onreadystatechange = function (){if(xhr.readyState == 4 && xhr.status == 200){var text = xhr.responseText;console.log(text);}
}

2. AJAX 请求状态

  • xhr.readyState 可以用来查看请求当前的状态
  • readyState

readystate是xhr对象中的属性,表示状态0, 1, 2, 3, 4:

  • 0: 表示 XMLHttpRequest 实例已经生成,但是 open()方法还没有被调用。
  • 1: 表示 send()方法还没有被调用,仍然可以使用 setRequestHeader(),设定 HTTP请求的头信息。
  • 2: 表示 send()方法已经执行,并且头信息和状态码已经收到。
  • 3: 表示正在接收服务器传来的 body 部分的数据。
  • 4: 表示服务器数据已经完全接收,或者本次接收已经失败了

3. AJAX发送GET请求

需求:点击按钮,向服务端发送请求,把从服务端返回的响应体结果在文本框里面展示出来(在div里面做一个呈现)

3.1 GET.html

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AJAX GET 请求</title><style>#result {width: 200px;height: 100px;border: solid 1px #90b;}</style>
</head>
<body><button id="result1">点击发送请求</button><div id="result"></div><script>// 获取button元素const btn = document.getElementById('result1');const result = document.getElementById('result');// 绑定事件btn.onclick = function () {// 1. 创建 XMLHttpRequest 对象const xhr = new XMLHttpRequest();// 2. 初始化 设置请求方法和 urlxhr.open('GET', 'http://127.0.0.1:8000/server');// 发送请求xhr.send();// 4. 事件绑定 处理服务端返回的结果xhr.onreadystatechange = function () {// 判断(服务端返回了所有的结果)if(xhr.readyState === 4) {// 判断响应状态码 200 404 403 401 500// 2xx 成功if (xhr.status >= 200 && xhr.status < 300) {// // 处理结果 行 头 空行 体// // 1. 响应行// console.log(xhr.status); // 状态码// console.log(xhr.statusText); // 状态字符串// console.log(xhr.getAllResponseHeaders()); // 所有响应头// console.log(xhr.response); // 响应体// 设置 result 的文本result.innerHTML = xhr.response;}}}}</script>
</body>
</html>

3.2 server.js

// 1. 引入express
const express = require('express');// 2. 创建应用对象
const app = express();// 3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/server', (request, response) => {// 设置响应头  设置允许跨域response.setHeader('Access-Control-Allow-Origin', '*');// 设置响应体response.send('Hello AJAX');
});// 4. 监听端口启动服务
app.listen(8000, () => {console.log('服务已经启动, 8000 端口监听中....');
});

3.3 AJAX设置GET请求参数

  • 直接在url后面用?分割,然后加参数的名与值
  • 如果有多个参数就用&分开
    在这里插入图片描述

4. AJAX发送POST请求

需求:鼠标光标移进文本框,就会向服务端发送请求,服务端返回结果,然后把结果在该框中做一个呈现

4.1 POST.html

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AJAX POST 请求</title><style>#result {width: 200px;height: 100px;border: solid 1px #903;}</style>
</head>
<body><div id="result"></div><script>// 获取元素对象const result = document.getElementById('result');// 绑定事件result.addEventListener("mouseover", function () {// 1. 创建对象const xhr = new XMLHttpRequest();// 2. 初始化 设置类型 与URLxhr.open('POST', 'http://127.0.0.1:8000/server');// 3. 发送xhr.send(a=100);// 4. 事件绑定xhr.onreadystatechange = function () {// 判断if (xhr.readyState === 4) {// 判断状态码if (xhr.status >= 200 && xhr.status < 300) {// 处理服务端返回的结果result.innerHTML = xhr.response;}}}})</script>
</body>
</html>

4.2 server.js

// 1. 引入express
const express = require('express');// 2. 创建应用对象
const app = express();// 3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装app.post('/server', (request, response) => {// 设置响应头  设置允许跨域response.setHeader('Access-Control-Allow-Origin', '*');// 设置响应体response.send('Hello AJAX POST');
});// 4. 监听端口启动服务
app.listen(8000, () => {console.log('服务已经启动, 8000 端口监听中....');
});

4.3 post设置参数

  • 直接在send里面设置参数
  • 可以自己设置格式,只要服务端能够处理
    在这里插入图片描述
    在这里插入图片描述

5. 设置请求头信息

  • 设置预设头信息
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  • 设置自定义头信息
xhr.setRequestHeader('name', '123');// node.js设置
//请求类型改为all
app.all// 设置可接收自定义请求
response.setHeader('Access-Control-Allow-Headers', '*');

6. 服务端响应JSON数据

需求:按下键盘上的任意按键,就会向服务端发送请求,服务端返回结果,然后把结果在div中做一个呈现

6.1 处理json数据

  1. 因为响应体只能发送字符串,我们可以先在服务端把要响应的数据对其进行字符串转换之后再将其发送

  2. 在客户端处理数据有两种方法,一是手动处理,二是自动处理(用的多)

  3. 手动处理:将接受到的字符串进行json格式的转换let data = JSON.parse(xhr.response);

  4. 自动处理:在前面设置好响应体的数据类型:xhr.responseType = 'json';,后面直接用该数据就行

6.1 JSON.html

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>JSON响应</title><style>#result {width: 200px;height: 100px;border: solid 1px #903;}</style></head>
<body><div id="result"></div><script>// 获取元素对象const result = document.getElementById('result');// 绑定键盘按下事件window.onkeydown = function () {// 1. 创建对象const xhr = new XMLHttpRequest();// 设置响应体数据的类型(自动转换)xhr.responseType = 'json';// 2. 初始化 设置类型 与URLxhr.open('GET', 'http://127.0.0.1:8000/json-server');// 3. 发送xhr.send();// 4. 事件绑定xhr.onreadystatechange = function () {// 判断if (xhr.readyState === 4) {// 判断状态码if (xhr.status >= 200 && xhr.status < 300) {// 处理服务端返回的结果// console.log(xhr.response);// result.innerHTML = xhr.response;// 处理数据第一种方法:手动对数据转换// let data = JSON.parse(xhr.response);// result.innerHTML = data.name;// 处理数据第二种方法:自动转换console.log(xhr.response);result.innerHTML = xhr.response.name;}}}}</script>
</body>
</html>

6.2 server.js

// 1. 引入express
const express = require('express');// 2. 创建应用对象
const app = express();// 3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装app.all('/json-server', (request, response) => {// 设置响应头  设置允许跨域response.setHeader('Access-Control-Allow-Origin', '*');// 响应头response.setHeader('Access-Control-Allow-Headers', '*');// 响应一个数据const data = {name:'张三'};// 对对象进行字符串转换let str = JSON.stringify(data);// 设置响应体response.send(str);
});// 4. 监听端口启动服务
app.listen(8000, () => {console.log('服务已经启动, 8000 端口监听中....');
});

7. nodemon自动重启工具安装

  • 每次修改js文件都需要停掉服务重新启动,比较麻烦,这个工具会在检测到js文件修改后自动重启服务

7.1 nodemon的安装

  1. 停掉服务:ctrl + c
  2. 终端输入npm install -g nodemon进行nodemon的安装

7.2 nodemon启动服务

  1. 启动服务:nodemon server.js
  2. 后面只要该文件server.js被修改,服务会自动重新启动

8. 解决 IE 缓存问题

  • IE缓存问题:IE浏览器会对AJAX的一个请求结果做一个缓存,会导致一个问题:下一次发送请求的时候,走得是本地的缓存,而非服务器返回的最新数据,在一些时效性比较强的场景,ajax缓存会影响我们的结果,它不能够正常去显示
  • 问题:在一些浏览器中(IE),由于缓存机制的存在,ajax 只会发送的第一次请求,剩余多次请求不会在发送给浏览器而是直接加载缓存中的数据。
  • 解决方式:浏览器的缓存是根据 url 地址来记录的,所以我们只需要修改 url 地址即可避免缓存问题。我们给url后面加一个“获取当前时间的时间戳”,因为时间不同,所以url不同,浏览器会认为这是两次不同的请求,这个时候客户端会发送一个新的请求而非走本地缓存
    xhr.open("get","/testAJAX?t="+Date.now());

8.1 IE缓存问题.html

<!DOCTYPE html>
<html lang="zh-CN">
<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 #258;}</style>
</head>
<body><button>点击发送请求</button><div id="result"></div><script>const btn = document.getElementsByTagName('button')[0];const result = document.querySelector('#result');btn.addEventListener('click', function(){console.log("test");const xhr = new XMLHttpRequest();xhr.open("GET", 'http://127.0.0.1:8000/ie?t=' + Date.now());xhr.send();xhr.onreadystatechange = function() {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) {result.innerHTML = xhr.response;}}}})</script>
</body>
</html>

8.2 server.js

// 1. 引入express
const express = require('express');// 2. 创建应用对象
const app = express();// 3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装// 针对IE缓存
app.get('/ie', (request, response) => {// 设置响应头  设置允许跨域response.setHeader('Access-Control-Allow-Origin', '*');// 设置响应体response.send('Hello IE');
});// 4. 监听端口启动服务
app.listen(8000, () => {console.log('服务已经启动, 8000 端口监听中....');
});

9. 请求超时与网络异常处理

通过ajax给超时做一个设置,来及时给客户做一个提醒,并且在网络异常的时候也给用户来一个友好的提醒

  • 如果2s后还没有返回结果,就来一个提醒,告诉客户网络超时,请稍后重试
  • 如果网络异常,则返回一个提醒

9.1 超时与网络异常.html

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>超时与网络异常</title><style>#result {width: 200px;height: 100px;border: solid 1px #90b;}</style>
</head>
<body><button>点击发送请求</button><div id="result"></div><script>// 获取元素对象const btn = document.getElementsByTagName('button')[0];const result = document.getElementById('result');// 绑定事件btn.addEventListener("click", function () {// 1. 创建对象const xhr = new XMLHttpRequest();// 超时设置 2s 设置xhr.timeout = 2000;// 超时回调xhr.ontimeout = function () {result.innerHTML = "请求超时";}// 网络异常xhr.onerror = function () {alert("网络异常");}// 2. 初始化 设置类型 与URLxhr.open('GET', 'http://127.0.0.1:8000/delay');// 3. 发送xhr.send();// 4. 事件绑定xhr.onreadystatechange = function () {// 判断if (xhr.readyState === 4) {// 判断状态码if (xhr.status >= 200 && xhr.status < 300) {// 处理服务端返回的结果result.innerHTML = xhr.response;}}}})</script>
</body>
</html>

9.2 server.js

// 1. 引入express
const express = require('express');// 2. 创建应用对象
const app = express();// 3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装// 延时响应
app.get('/delay', (request, response) => {// 设置响应头  设置允许跨域response.setHeader('Access-Control-Allow-Origin', '*');// 延时响应setTimeout(() => {response.send('延时响应');}, 3000);
});// 4. 监听端口启动服务
app.listen(8000, () => {console.log('服务已经启动, 8000 端口监听中....');
});

9.3 断网测试

-

10. 取消请求

  • 通过代码手动取消请求
  • status:pending是处于发送过程中
  • status:cancel是取消发送

10.1 取消请求.html

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=q, initial-scale=1.0"><title>取消请求</title>
</head>
<body><button>点击发送</button><button>点击取消</button><script>// 获取元素对象const btns = document.querySelectorAll('button');let x = null;// const controller = new AbortController();btns[0].onclick = function() {const x = new XMLHttpRequest();x.open('GET', 'http://127.0.0.1:8000/cancel');x.send();}// abortbtns[1].onclick = function() {// controller.abort();x.abort();}</script>
</body>
</html>

10.2 server.js

// 1. 引入express
const express = require('express');// 2. 创建应用对象
const app = express();// 3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装// 取消请求
app.get('/cancel', (request, response) => {// 设置响应头  设置允许跨域response.setHeader('Access-Control-Allow-Origin', '*');// 取消请求setTimeout(() => {response.send('取消请求');}, 3000);
});// 4. 监听端口启动服务
app.listen(8000, () => {console.log('服务已经启动, 8000 端口监听中....');
});

11. 请求重复发送问题

  • 解决办法 :当点击发送第二个相同的请求的时候,把第一个请求取消掉

解决步骤:

  1. 定义一个标识变量isSending为false
  2. 修改isSending为true表示发送请求
  3. 当readyState为4的时候表示请求完成,修改isSending为false
  4. 连续发送请求,但是此时的isSending还是true,所以取消该请求重新发送
  5. 如果连续发送请求,都会取消上一个发送的请求来保证只有一个请求发出,减少服务器压力

11.1 重复请求问题.html

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=q, initial-scale=1.0"><title>取消请求</title>
</head>
<body><button>点击发送</button><script>// 获取元素对象const btns = document.querySelectorAll('button');let x = null;// 标识变量let isSending = false;  // 是否正在发送Ajax请求// const controller = new AbortController();btns[0].onclick = function() {// 判断标识变量if (isSending) x.abort();  // 如果正在发送Ajax请求,则取消请求,创建一个新的请求// 修改 标识变量的值isSending = true;x = new XMLHttpRequest();x.open('GET', 'http://127.0.0.1:8000/cancel');x.send();x.onreadystatechange = function() {if (x.readyState === 4) {// 修改标识变量isSending = false;}}}</script>
</body>
</html>

11.2 server.js

// 1. 引入express
const express = require('express');// 2. 创建应用对象
const app = express();// 3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装// 重复请求
app.get('/cancel', (request, response) => {// 设置响应头  设置允许跨域response.setHeader('Access-Control-Allow-Origin', '*');// 取消请求setTimeout(() => {response.send('重复请求');}, 3000);
});// 4. 监听端口启动服务
app.listen(8000, () => {console.log('服务已经启动, 8000 端口监听中....');
});

这篇关于第 2 章:AJAX 的使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1141055

相关文章

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景