当前位置: 首页 > news >正文

第 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 端口监听中....');
});

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 第 1 章:原生 AJAX
  • 使用isolation: isolate声明隔离混合模式
  • day50——QT
  • HarmonyOS开发实战( Beta5.0)系统提供的接口实践规范
  • 从知识视角理解软件开发
  • 2023 CCPC(秦皇岛)现场(第二届环球杯.第 2 阶段:秦皇岛)部分题解
  • 【2024数模国赛赛题思路公开】国赛B题第二套思路丨附可运行代码丨无偿自提
  • 4000字三合一!Stata、SPSS、MATLAB实现多元线性回归详解!
  • 高等代数精解【9】
  • flutter开发多端平台应用的探索 上(基本操作)
  • 监理工程师职业资格考试
  • 如何在Mac电脑上本地部署Stable Diffusion:详细教程(webUI)
  • 基于SVM的手势识别,SVM工具箱详解,SVM工具箱使用注意事项
  • nnunetv2(一)配置文件和nnUNetv2_convert_MSD_dataset命令
  • JZ62 孩子们的游戏(圆圈中最后剩下的数)
  • 深入了解以太坊
  • 30秒的PHP代码片段(1)数组 - Array
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • input的行数自动增减
  • Javascript基础之Array数组API
  • js操作时间(持续更新)
  • python_bomb----数据类型总结
  • React中的“虫洞”——Context
  • vuex 笔记整理
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 工作中总结前端开发流程--vue项目
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 前端自动化解决方案
  • 嵌入式文件系统
  • 如何合理的规划jvm性能调优
  • 如何利用MongoDB打造TOP榜小程序
  • 掌握面试——弹出框的实现(一道题中包含布局/js设计模式)
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • #etcd#安装时出错
  • #git 撤消对文件的更改
  • #微信小程序:微信小程序常见的配置传值
  • ( 用例图)定义了系统的功能需求,它是从系统的外部看系统功能,并不描述系统内部对功能的具体实现
  • (7)摄像机和云台
  • (C语言)字符分类函数
  • (二刷)代码随想录第15天|层序遍历 226.翻转二叉树 101.对称二叉树2
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (附源码)ssm本科教学合格评估管理系统 毕业设计 180916
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (算法)硬币问题
  • (原)Matlab的svmtrain和svmclassify
  • (转)3D模板阴影原理
  • .axf 转化 .bin文件 的方法
  • .net core使用EPPlus设置Excel的页眉和页脚
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .Net程序帮助文档制作