Ajax简介
AJAX 全称为Asynchronous JavaScript And XML,通过Ajax可以在浏览器中向服务器发送异步请求(无刷新获取数据)。
Ajax优缺点
优点:
- 不需要刷新页面就能与服务器端进行通信
- 可以根据用户的事件进行部分页面的更新(比如懒加载)
缺点: - 由于页面并没有刷新,不能回退,没有浏览历史
- 存在跨域的问题
- 对SEO不友好
HTTP
HTTP是一种通讯协议(protocol),是在Web上进行数据交换的基础。请求通常是由像浏览器这样的接受方发起的。客户端和服务器通过交换各自的消息进行交互。
- request:客户端发出的消息(浏览器)。
- response:被服务端响应的消息。
http协议应用的过程:用户代理(大多数情况下是浏览器)发出一个请求(request),经过一些被称为Proxy的实体,发送到服务器。服务器处理请求并返回一个信息(response),信息经过一些Proxy再发送到浏览器。
http报文
http报文包含两种类型,请求与响应。
请求报文:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EhluTN3M-1676806839201)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/60cb70ca764a49b3805dd44b508976df~tplv-k3u1fbpfcp-watermark.image?)]
http请求包含以下部分:
- method:用于定义客户端的行为。method包括:
- GET:从服务器端读取数据的请求
- POST: 向服务器端添加数据的请求
- …
- Path:要获取元素资源的路径
- Version of the protocol:http协议版本号
- Headers: 可选头部(为服务端表达其他信息)
- body(可选项):包含发送的资源
请求报文也可以概括为由四部分组成:行(method,path和协议版本号组成了行。)、头(headers)、空行、体(body)。
http响应包含以下部分
- Version of the protocol:http协议版本号。
- Status code:状态码,来告知对应请求执行成功或失败,以及失败的原因。
- Status message:状态信息,状态码的描述信息,可以由服务端自行设定。状态码与状态信息示例:
- 200 OK,表示请求成功;
- 404 Not Found, 服务器无法根据客户端的请求找到资源;
- …
- headers:头部。
- body(可选项):包含获取的资源,相对于请求报文响应报文更常见地包含body。
请求报文也可以概括为由四部分组成:行(http协议版本号,状态码和状态信息组成了行。)、头(headers)、空行、体(body)。
express的使用
代码:
// 1.引入express
const express = require('express');
// 2.创建应用对象
const app = express();
// 3.创建路由规则
// /server会使得执行回调函数内的代码,并由response作出响应
app.get('/server',(request,response)=>{
response.setHeader('Access-Control-Allow-Origin','*');
response.send('hello');
});
// 4.监听端口启动服务
app.listen(8000,()=>{
console.log('服务已启动,8000端口监听中');
})
在终端运行程序
Ajax使用XHR
XHR(XMLHttpRequest)用于发送ajax请求。
使用XHR:
1.创建并初始化XHR,绑定相应事件
<script>
// 获取元素
var btn = document.querySelector('button');
var div = document.querySelector('.result');
//使用XHR
btn.onclick = function(){
// 1.创建对象
const xhr = new XMLHttpRequest();
// 2.初始化 设置请求方法和url
xhr.open('GET','http://127.0.0.1:8000/server');
// 3.发送
xhr.send();
// 4.事件绑定 处理服务器端返回的结果
xhr.onreadystatechange = function(){
// 判断服务器端返回了所有的结果
if(xhr.readyState === 4){
if(xhr.status>=200 && xhr.status<300){
console.log(xhr.status);//状态码
console.log(xhr.statusText);//状态字符串
console.log(xhr.getAllResponseHeaders);//所有响应头
console.log(xhr.response);//响应体
div.innerHTML = xhr.response;
}
}
}
}
</script>
readystate是xhr对象中的属性,有五个表示状态的值:0,1,2,3,4。
- 0:最开始的属性值
- 1:open方法已经调用完毕
- 2:send方法已经调用完毕
- 3:服务端返回了部分的结果
- 4:服务端返回了所有的结果
2. 启动之前的js文件
3.观察运行结果
运行后点击按钮,浏览器向服务器端发送请求,服务器端接收到请求进行处理后发送response,浏览器打印输出response信息。

在Ajax中设置url参数
直接在XHR中进行设置,xhr.open('GET','http://127.0.0.1:8000/server');
在url后面设置,
比如:xhr.open('GET','http://127.0.0.1:8000/server?a=1&b=2&c=3');
设置效果

在Ajax中发送POST请求设置请求体
在Ajax中发送POST请求直接更改初始化时的参数即可,xhr.open('POST','http://127.0.0.1:8000/server')
,将第一个参数改为POST。
可以通过send()方法设置请求体。在send()中设置请求体的格式并不固定,但要服务端可以进行处理。
const div = document.querySelector('div');
// 绑定事件
div.addEventListener('mouseover',function(){
// 创建对象
const xhr = new XMLHttpRequest();
// 初始化
xhr.open('POST','http://127.0.0.1:8000/server');
// 可以在send设置请求体
// 请求体的数据格式不是确定的,但要服务端可以处理
// 发送
xhr.send('a=1&b=2&c=3');
// 事件绑定,处理服务器端返回的结果
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
div.innerHTML = xhr.response;
}
}
}
})
查看效果

在Payload中查看请求体。
在Ajax中设置请求头信息
直接在初始化(xhr.open())之后用setRequestHeader()设置请求头的信息,比如:xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
查看效果
增加了Content-Type这条信息。
响应JSON数据请求
js文件:
const express = require('express');
const app = express();
app.get('/json-server',(request,response)=>{
// 设置响应头允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
// 响应数据
const data = {
name:'mike'
}
// 将对象转化为字符串(send()只能传输字符串)
let strData = JSON.stringify(data);
response.send(strData);
});
app.listen(8000,()=>{
console.log('服务器已启动,8000端口监听中');
});
在发送数据的时候要把数据转换成字符串格式(用JSON.stringify())才能发送。
html文件:
<script>
const div = document.querySelector('div');
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){
// 手动对数据进行转化
// let data = JSON.parse(xhr.response);
// div.innerHTML = data.name;
// 自动进行转换
div.innerHTML = xhr.response.name;
}
}
}
</script>
在接收到响应后可以通过手动对数据进行转化或者设置响应体的数据类型进行自动转化。
查看效果:

超时或网络异常设置
服务器端的部分代码:
app.get('/delay',(request,response)=>{
// 设置响应头允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
// 延时响应
setTimeout(function(){
response.send('IE')
},3000)
});
设置延时响应来测试请求超时的情况。
客户端部分代码:
btn.onclick = function(){
const xhr = new XMLHttpRequest();
// 超时设置
xhr.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){
console.log(xhr.response);
div.innerHTML = xhr.response;
}
}
}
}
超时设置为2s,当响应超过两秒还没返回时就调用超时回调函数,当网络异常时调用网络异常回调函数。
查看效果

手动取消Ajax请求
在发送请求,服务端未返回相应之前可以手动取消请求,调用abort()
。
服务器端代码仍用上面延迟例子的代码。
客户端代码:
<script>
const btns = document.querySelectorAll('button');
let xhr = null;
//点击发送请求的效果
btns[0].onclick = function(){
xhr = new XMLHttpRequest();
xhr.open('GET','http://127.0.0.1:8000/delay');
xhr.send();
}
//点击取消请求的效果
btns[1].onclick = function(){
//利用abort()取消请求
xhr.abort();
}
</script>
查看效果

可见红色delay是点击取消按钮后手动取消的请求。
解决请求重复发送
当用户一直点击发送请求的按钮时,浏览器就会不断地向服务端发送请求,这时服务端的压力就很大。因此当用户重复发送请求时就取消之前的请求发送,只保留最新的请求。
服务器的代码沿用上面延迟的代码。
html文件部分代码:
<body>
<button>点击发送请求</button>
<script>
const btns = document.querySelectorAll('button');
let xhr = null;
// 标识变量,标识是否正在发送请求
let flag = false;
btns[0].onclick = function(){
// 判断是否正在发送请求,如果是则取消该请求重新创建一个
if(flag){
xhr.abort();
}
xhr = new XMLHttpRequest();
// 正在发送请求
flag = true;
xhr.open('GET','http://127.0.0.1:8000/delay');
xhr.send();
// 当readyState为4时,表示完成请求且服务端已经返回全部结果
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
// 一个请求结束,修改标识变量
flag = false;
}
}
}
</script>
</body>
主要方法是创造一个标识变量来标识之前的请求是否完成,如果之前的请求正在发送则用abort()取消请求,重新发送。(用readyState()来衡量请求是否完成)
查看效果

可见当重复发送请求时,之前的请求都被取消,只有最新的请求被保留。
在以上过程中用到的部分API
XMLHttpRequest
:创建XHR对象的构造函数XMLHttpRequest.open(method,url,async,user,password)
:初始化一个请求XMLHttpRequest.send(body)
:发送HTTP请求XMLHttpRequest.onreadystatechange
:只要readyState
属性发生变化,就会调用相应的处理函数XMLHttpRequest.readyState
:返回一个 XMLHttpRequest 代理当前所处的状态XMLHttpRequest.status
:返回状态码XMLHttpRequest.abort()
:当请求已被发出时,该方法用于终止该请求。- …
利用jQuery发送Ajax
发送get请求
$.get('http://127.0.0.1:8000/jquery-server',{a:1,b:2},function(data){
console.log(data);
},'json')
get的语法:$.get(URL,data,function(data,status,xhr),dataType)。
发送post请求
$.get('http://127.0.0.1:8000/jquery-server',{a:1,b:2},function(data){
console.log(data);
},'json')
post的语法:$(selector).post(URL,data,function(data,status,xhr),dataType)
利用axios发送Ajax请求
使用方法见
相关github文档。
引入axios时,可以用BootCDN的链接代替github的链接,会快一点
利用fetch函数发送Ajax请求
示例:
btn.onclick = function(){
fetch('http://127.0.0.1:8000/fetch-server?a=1&b=2',{
// 请求方法
method:'POST',
// 请求头
headers:{
name:'mike'
},
// 请求体
body:'username=mike'
}).then(response =>{
console.log(response);
})
}
详细参数设置见文档。
同源策略
同源策略是浏览器的一种安全策略。同源:协议、域名、端口号必须完全相同。违背同源策略就是跨域。