1.什么是Ajax?
Ajax又叫异步js或者xml,是浏览器和服务器之间的通信技术,可以在不刷新网页的基础上向服务器发送HTTP请求,获取数据。
2.使用Ajax的优缺点
优点:不刷新页面请求数据,允许用户根据事件部分更新内容
缺点:没有历史,无法回退;存在跨越问题;SEO不友好
3.同源策略
通俗地说就是指浏览器和服务器所遵守的协议,端口号和域名都必须相同,否则就会出现跨域问题,Ajax默认接受同源策略。
4.什么是HTTP协议
HTTP协议又叫超文本传输协议,规定了浏览器和万维网之间通信的规则,里面包含有请求报文和响应报文。
请求报文包含:请求行,请求头,空行,请求体
请求行:请求类型、url、协议版本等
请求头:host、cookie、content-type、user-agent等等
请求体:GET请求没有请求体,POST请求可以携带请求体
响应报文包含:响应行,响应头,空行,响应体
响应行:协议版本、状态码、状态码字符串
响应头:对响应内容的描述,内容格式,长度等等
响应体:服务器响应给客户端的内容
5.使用Ajax发送请求
步骤:
a 创建XMLHttpRequest对象
b 初始化对象 设置请求方式和请求url
c 发送请求
d 监听事件 对返回数据进行处理
readyState是XMLHttpRequest实例的一个属性用来表示状态,有五个值 0(未初始化) 1(已调用open方法初始化) 2(已调用send方法发送请求) 3(服务器返回部分数据) 4(服务器已经返回全部数据),需要监听该属性的改变,当该属性值为4时,服务器端已经将结果全部发送给用户,此时用户再根据响应的状态码进行判断,状态码大于200小于300都属于成功,如果状态码表示成功,此时用户就可以进行数据的处理。
这是一个简单的GET请求
//1.创建对象
const xhr = new XMLHttpRequest();
//2.初始化 设置请求方式和url
xhr.open("GET", "http://127.0.0.1/server");
//3.发送
xhr.send();
//4.事件绑定处理服务器端返回的结果
//on 监听事件
//readystate xhr的属性 表示状态 有5个状态
//0 未初始化 1已经调用open 2已经调用send方法 3服务器返回部分结果 4服务器返回所有结果
//change 事件改变 改变4次 0-1 1-2 2-3 3-4
xhr.onreadystatechange = function () {
//当状态为4时处理服务器返回的结果
if (xhr.readyState === 4) {
//判断响应状态码 如果状态码大于200小于300都为成功
if (xhr.status >= 200 && xhr.status <= 300) {
//处理结果
console.log(xhr.status); //状态码
console.log(xhr.statusText); //状态码字符串
console.log(xhr.getAllResponseHeaders); //响应头
console.log(xhr.response); //响应体
result.innerHTML = xhr.response;
}
}
};
POST请求,并且设置请求头
//创建对象
const xhr = new XMLHttpRequest();
//初始化对象
xhr.open("POST", "http://127.0.0.1/server");
//设置请求头 请求头名字,请求头值
//可以自定义请求头 但是浏览器会报错 需要服务器端进行设置
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
//发送 请求体内容在这设置 请求体可以是任意格式数据 前提是服务端可以处理
xhr.send("username=zhangya&password=aaaaaa");
//事件绑定
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status <= 300) {
result.innerHTML = xhr.response;
}
}
};
在设置请求头时,用户可以自定义请求头,但是自定义的请求头必须在服务器端先预定义,否则会报错。
6.解决IE浏览器的缓存问题
IE浏览器回对Ajax的结果进行缓存,当客户再次请求相同的url时会从本地缓存中获取数据,就不会获取到最新的数据,对于时效性比较强的场景,这样会大大影响数据的价值。以下时解决该问题的示例代码:
//创建对象
const xhr = new XMLHttpRequest();
//初始化对象
xhr.open("POST", "http://127.0.0.1/server?t="+ Date.now());
//设置请求头 请求头名字,请求头值
//可以自定义请求头 但是浏览器会报错 需要服务器端进行设置
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
//发送 请求体内容在这设置 请求体可以是任意格式数据 前提是服务端可以处理
xhr.send("username=zhangya&password=aaaaaa");
//事件绑定
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status <= 300) {
result.innerHTML = xhr.response;
}
}
};
我们只需要在url中添加一个每次都不同的参数,在这里使用的是获取当时的时间戳,每个时间的时间戳都不一样,而且不需要我们进行手动改变该参数。这样每次的url都不一样,也就不会出现走缓存的现象。
7.数据转换
服务器返回给我们的一般都是JSON字符串,从字符串中获取我们想要的数据会比较复杂,当然我们可以使用JSON.parse()方法手动将数据转换为对象,也可以使用实例对象的responseType属性来自动进行数据处理例如这样:
const xhr = new XMLHttpRequest();
//自动处理数据
xhr.responseType = "json";
8.解决请求超时和网络问题
先看代码
xhr.open("GET", "http://127.0.0.1/time");
// xhr.responseType = "json";
xhr.setRequestHeader(
"Content-Type",
"application/x-www-form-urlencoded"
);
//超时设置 2s
xhr.timeout = 2000;
//超时回调
xhr.ontimeout = () => {
alert("请求超时请稍后重试!");
};
//网络异常回调
xhr.onerror = () => {
alert("你的网络似乎出现了问题!");
};
xhr.send("name=zhangsan&age=18");
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
box.innerHTML = xhr.response;
}
}
};
首先我们设置了一个2秒的时间
xhr.timeout = 2000;
然后监听这个时间
xhr.ontimeout = () => {
alert("请求超时请稍后重试!");
};
并给它设置一个超时的回调函数,如果在这个时间内,服务器没有对这次请求做出响应,那么就会触发这个回调函数给出提示。
另外我们设置了一个error的回调函数,当网络出现异常时也会触发
xhr.onerror = () => {
alert("你的网络似乎出现了问题!");
};
我们可以打开开发者工具然后关闭网络来进行测试
脱机之后进行请求就会alert出相应的提示。
9.处理多次相同的请求
用户在间隔很短的时间内多次重复的进行相同的请求,这时服务器还没来得及进行反应,那么就会给服务器造成很大的负担,这是一个很严重的问题。
我们可以设置一个标识变量,然后根据该变量的值来决定是否发起请求
let xhr = null;
//表示变量
let isSending = false; //是否正在发送请求
btns[0].onclick = () => {
//判断是否正在发送请求 是 则取消请求
if (isSending) xhr.abort();
xhr = new XMLHttpRequest();
isSending = !isSending;
xhr.open("GET", "http://127.0.0.1/time");
xhr.send();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
isSending = !isSending;
}
};
我们设置了isSending的初始值为false,这时未发送请求,当发送请求时将该值取反未true,在发送请求时判断该值如果为true则调用abort方法取消该次请求
if (isSending) xhr.abort();
当请求完成后,又将该值取反false。这样就不会影响下一次请求。
10.Ajax在Jquery中的通用形式以及一般形式
一般形式
$.get('http:127.0.0.1/server',{username:'zhangsan','age':18},(data)=>{
console.log(data)
})
通用形式
$.ajax({
url:'http://127.0.0.1/server',
data:{username:'zhangsan','age':18},
type:'GET',
dataType;'json', //响应结果处理
success:(data)=>{
console.log(data)
},
timeout:2000, //超时时间
error:()=>{
console.log('出错啦!') //出错回调
},
headers: //设置请求头
})
11 解决跨域问题
相信该问题是困扰很多人的一个头疼问题,这里我们使用CORS来解决该问题,也就是在服务器端设置响应头来允许那些携带了我们设置的允许访问的响应头的请求来进行访问。
Access-Control-Allow-Origin: http://example.com
当然我们也可以在服务器端使用代理来解决这个问题。
另外一个解决该问题的办法就是JSONP,在HTML标记语言中又许多的标签都包含跨域的特性例如当我们使用script标签引用外部js时,我们需要从某些网址引入,而我们本身的文件遵循的是file协议,引入的文件遵循的是http协议,这里就发生了跨域,但我们在使用这些引入的文件时并没有报跨域错误,JSOP解决跨域问题使用的就是这个原理,在这里我就不进行更多的赘述了。
能够进行服务器请求的还有很多例如axios、fetch等感兴趣的话大家可以去找相关资料看看。