一、Ajax简介
1.Ajax相关
AJAX 全称为Asynchronous Javascript And XML,就是异步的 JS 和 XML。
通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。
AJAX 不是新的编程语言,不是新的一门独立的技术,而是一种使用现有标准的新方法。
2.XML相关
XML 可扩展标记语言。
XML 被设计用来传输和存储数据。
XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全都是自定义标签,用来表示一些数据。
例如一个学生数据:name = "孙悟空" ; age = 18 ; gender = "男" ;
用XML表示:
<student>
<name>孙悟空</name>
<age>18</age>
<gender>男</gender>
</student>
用JSON表示:{"name":"孙悟空","age":18,"gender":"男"}
如今XML已经被JSON取代了
3.Ajax的工作原理
Ajax的工作原理相当于在用户和服务器之间加了一个中间层(Ajax引擎),使用户操作与服务器响应异步化。
4.Ajax的特点
- 优点
可以无需刷新页面而与服务器端进行通信。
允许你根据用户事件来更新部分页面内容。 - 缺点
没有浏览历史,不能回退
存在跨域问题
SEO不友好
二、原生Ajax
1.原生Ajax发送get请求
步骤:
-
实例化一个XMLHttpRequest对象
XMLHttpRequest是核心对象,Ajax的所有操作都是通过该对象进行的。 -
给对象绑定一个事件监听
在xhr内部有五种状态
- 0:当xhr被实例化出来,状态就是0,即初始化状态
- 1:请求还没有发出去,即:send方法还没有被调用,依然可以修改请求头
- 2:请求已经发出去了,即:send方法已经被调用了,不能再修改请求头,响应首行和响应头已经回来了
- 3:数据回来了,但是数据可能不完整,如果数据小,会在此阶段直接接受完毕,数据大则有待于进一步接受
- 4:数据完全回来了
-
指定发送请求的方式,地址,参数
-
发送请求
btn.onclick=function(){
//1.实例化一个XMLHttpRequest对象
const xhr=new XMLHttpRequest();
//2.给对象绑定一个事件监听
xhr.onreadystatechange=function(){
if(xhr.readyState===4&&xhr.status===200){
console.log(xhr.response);
let demo=document.getElementById("demo");
demo.innerHTML=xhr.response;
}
};
//3.指定发送请求的方式,地址,参数
xhr.open("GET","http://localhost:3000/test_get?name=dexter&&age=20");
//4.发送请求
xhr.send();
};
对于readyState
状态码的说明
一般不会在0,1,2,3这几种状态的回调中,做任何逻辑
const xhr=new XMLHttpRequest();
if(xhr.readyState===0){
console.log("我出生了");
}
xhr.onreadystatechange = function () {
if (xhr.readyState === 1) {
xhr.setRequestHeader("demo", 123);
console.log("请求还没有发出去,即:send方法还没有被调用,依然可以修改请求头");
}
if (xhr.readyState === 2) {
//如果在这里修改请求头会报错
console.log("请求已经发出去了,即:send方法已经被调用了,不能再修改请求头,响应首行和响应头已经回来了");
console.log(xhr.getResponseHeader("Date"));//Wed, 14 Oct 2020 12:28:58 GMT
}
if (xhr.readyState === 3) {
console.log("数据回来了,但是数据可能不完整,如果数据小,会在此阶段直接接受完毕,数据大则有待于进一步接受");
console.log(xhr.response);//get请求发回的数据
}
if (xhr.readyState === 4) {
console.log("数据完全回来了");
}
};
2.原生Ajax发送post请求
步骤
- 实例化一个XMLHttpRequest对象
- 给对象绑定一个事件监听
- 指定发送请求的方式,地址,参数
- 设置post请求所特有的请求头
- 发送请求
btn.onclick=function(){
//1.实例化一个XMLHttpRequest对象
const xhr=new XMLHttpRequest();
//2.给对象绑定一个事件监听
xhr.onreadystatechange=function(){
if(xhr.readyState===4&&xhr.status===200){
console.log(xhr.response);
let demo=document.getElementById("demo");
demo.innerHTML=xhr.response;
}
};
//3.指定发送请求的方式,地址,参数
xhr.open("POST","http://localhost:3000/test_post");
//4.设置post请求所特有的请求头
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
//5.发送请求
xhr.send("name=dexter&&age=20");
};
post请求与get请求的区别是post请求需要设置特殊的请求头,在发送数据时是在send中发送而get请求则是以urlencoded编码形式发送。
3.IE中存在的问题
对于chrome和火狐来说,当请求地址不发生变化时,浏览器会尝试走协商缓存。但是对于IE只要请求的地址不发生变化,会直接走强缓存,这样会导致服务端修改了代码但是浏览器刷新不出来效果的情况。因此在开发中为了应对IE的强缓存,会在请求参数中加一个无关的时间戳参数。
const xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if(xhr.readyState===4&&xhr.status===200){
console.log(xhr.response);
let demo=document.getElementById("demo");
demo.innerHTML=xhr.response;
}
};
xhr.open("GET","http://localhost:3000/test_get?name=dexter&age=20&t="+Date.now());
xhr.send();
4.使用promise封装原生Ajax
- 定义发送Ajax发送请求的模板函数
function sendAjax(url,method,data){
return new Promise((resolve,reject)=>{
//1.创建xhr对象
let xhr=new XMLHttpRequest();
//2.绑定监听
xhr.onreadystatechange=function(){
if(xhr.readyState!==4){
return
}
if(xhr.readyState===4&&(xhr.status>=200&&xhr.status<300)){
const responseObj={
data:xhr.response,
status:xhr.status,
statusText:xhr.statusText
};
resolve(responseObj);
}else{
reject(new Error("请求出错了"));
}
};
//3.将传递过来的数据加工成urlencoded形式的编码
let dataKeys=Object.keys(data);//将对象的键封装成数组的形式
/* Array(3)
0: "m"
1: "n"
2: "r"
length: 3 */
let str=dataKeys.reduce(function(pre,now){
return pre+=`${now}=${data[now]}&`;
},""); //m=1&n=2&r=4&
//4.发送请求
if(method.toLowerCase()==="get"){
url+=`?${str}`;
xhr.open(method,url);
xhr.send();
}else if(method.toLowerCase()==="post"){
xhr.open(method,url);
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
xhr.send(str);
}
})
}
- 发送get请求
obj1={
m:1,
n:2,
r:4
};
btn1.onclick=function(){
sendAjax("http://localhost:3000/test_get","GET",obj1).then((data)=>{
console.log(data);
}).catch((err)=>{
console.log(err);
})
};
- 发送post请求
obj2={
name:"dexter",
age:25
}
btn2.onclick=function(){
sendAjax("http://localhost:3000/test_post","POST",obj2).then((data)=>{
console.log(data);
}).catch((err)=>{
console.log(err);
})
};
5.服务端代码
const { request, response } = require("express");
let express=require("express");
let app=express();
//暴露静态资源
app.use(express.static(__dirname+"/public"));
//解析psot请求请求体中的urlencoded形式的参数
app.use(express.urlencoded({extended:true}));
app.get("/test_get",(request,response)=>{
console.log("一个get请求来了",request.query);
response.send("get请求发回的数据");
})
app.post("/test_post",(request,response)=>{
console.log(request.body);
console.log("一个post请求来了");
response.send("post请求发回的数据");
})
app.listen(3000,(err)=>{
if(!err){
console.log("服务器已启动,3000端口正在监听");
}else{
console.log(err);
}
})
三、取消上一次请求
问题描述:
当用户点击鼠标发送一次请求在没有得到服务器响应之前再次点击了请求,或者连续多次发送请求,这样会导致服务器在反映过来后向用户多次返回相同的数据,造成用户体验较差。因此应当对这样的情况进行处理,即当用户连续多次的发送同样的请求时即使服务器当下处理不过来,在反应过来时也只给用户返回最后一次请求的数据。
let lastxhr
btn.onclick = function () {
if (lastxhr) {
lastxhr.abort();
/* abort()的工作方式
当用户点击的速度一般时,abort会追回用户的请求,服务器不会接收到用户的请求
当用户点击的速度非常快时以至于abort追不上时,abort会拦截服务器返回的数据 */
}
lastxhr = getcode();
};
function getcode() {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)) {
console.log(xhr.response);
}
};
xhr.open("GET", "http://localhost:3000/get_code");
xhr.send();
return xhr;
}
服务端代码
app.get("/get_code",(request,response)=>{
//返回一个1000-9999的数
console.log("页面请求验证码");
let code=Math.floor(Math.random()*8999+1000);
setTimeout(()=>{
response.send(code.toString());//如果返回一个纯数字服务器会以为返回的是状态码而报错
},2000)
})
四、使用jQuery封装Ajax
1.jQuery发送get请求
-
完整写法中常用的几个参数
--method: 发送请求的方式
--data: 要传递的数据
--success: 成功的回调
--error: 失败的回调
let btn1 = $("#btn1");
btn1.click(function () {
$.ajax("http://localhost:3000/test_get",{
method:"GET",
data:{
name:"dexter",
age:25
},
success:function(result){
console.log(result);
},
error:function(err){
console.log(err);
}
})
})
-
精简写法的参数
精简的写法直接传入请求地址和请求参数以及一个回调函数
这个回调函数会有三个形参:
第一个形参表示返回来的数据
第二个参数表示当前请求的状态
第三个参数是内部使用的xhr对象
但是一般在使用时只传进去一个参数,即服务器返回来的数据
$.get("http://localhost:3000/test_get", { name: "dexter", age: 25 }, (data) => {
console.log(data);
})
2.jQuery发送post请求
- 完整写法
btn2.click(function () {
$.ajax("http://localhost:3000/test_post",{
method:"POST",
data:{
name:"dexter",
age:25
},
success:function(result){
console.log(result);
},
error:function(err){
console.log(err);
}
})
})
- 精简写法
$.post("http://localhost:3000/test_post", { name: "dexter", age: 25 }, (data) => {
console.log(data);
})
网友评论