AJAX
一、简介
1.1 AJAX简介
- AJAX全称为Asynchronous Javascript And XML,即异步JS和XML
- 通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据
- AJAX不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式
1.2 XML简介
- XML:可扩展标记语言
- XML:被设计用来传输和存储数据
- XML和HTML类似,不同点:HTML中都是预定义标签,XML中没有预定义标签,全是自定义标签,用来表示一些数据
- 现在已被JSON取代
1.3 AJAX的特点
1.3.1 AJAX的优点
- 可以无刷新页面与服务端进行通信
- 允许你根据用户事件来更新部分页面内容
1.3.2 AJAX 的缺点
- 没有浏览历史,不能回退
- 存在跨域问题(同源)
- SEO不友好(爬虫获取不到信息)
1.4 HTTP
HTTP(hypertext transport protocol)协议【超文本传输协议】,协议详细规定了浏览器和万维网服务器之间互相通信的规则
1.4.1 请求报文
重点是格式与参数
行 请求类型:GET/POST 路径URL /s?ie=utf-8 协议版本HTTP/1.1
头 HOST: blog.sliber.cn
Cookie: name=LMK
Content-type: application/x-www-form-urlencoded
Uer-Agent: chrom 83
空行
体 username=admin&password=admin
1.4.2 相应报文
行 协议版本:HTTP/1.1 响应状态码200 响应字符串OK
头 Content-Type: text/html;charset=utf-8
Content-length: 2048
Content-encoding: gzip
空行
体 <html>
<head>
</head>
<body>
<h1>ajax学习</h1>
</body>
</html>
响应状态码
404 找不到
403 无权限
401 未授权
500 内部错误
200 ok
二、原生Ajax 及其使用
核心对象:XMLHttpRequest,AJAX的所有操作都是通过该对象进行的。
2.1 基本步骤
-
创建XMLHttpRequest对象
varxhr=newXMLHttpRequest();
-
设置请求信息
xhr.open(method,url);
-
// 可以设置请求头,一般不设置
// xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
AJAX请求需要设置withCredentials属性为true,以便允许跨域设置cookie。默认情况下,AJAX请求是不会发送cookie的。在发送AJAX请求前,设置
xhr.withCredentials = true
,让浏览器发送cookie。注意,服务器也需要在响应头中设置Access-Control-Allow-Credentials: true,允许跨域请求携带cookie。
xhr.withCredentials = true
为true就是使用本页面的cookie
// xhr.setRequestHeader('Cookie', document.cookie)
-
发送请求
xhr.send(body)
xhr.send('bookname=水浒传&author=施耐庵&publisher=上海图书出版社')
// get请求不传body参数,只有post请求使用 -
接收响应
xhr.onreadystatechange = function () {
//判断 (服务端返回了所有的结果)
if (xhr.readyState === 4) {
//判断响应状态码 200 404 403 401 500
// 2xx 成功
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;
console.log('xhr.response', xhr.response)
} else {
}
}
}
-
其他函数
- 设置响应体数据的类型,后面可以自动转换
xhr.responseType = "json"; - 超时设置
xhr.timeout = 2000; - 超时回调
xhr.ontimeout = function(){} - 网络异常回调
xhr.onerror = function(){} - 手动取消请求
xhr.abort();
- 设置响应体数据的类型,后面可以自动转换
2.2 AJAX请求状态
xhr.readyState 可以用来查看请求当前的状态
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/readyState
- 0 (UNSENT)
表示XMLHttpRequest实例已经生成,但是open()
方法还没有被调用。 - 1 (OPENED)
表示send()
方法还没有被调用,仍然可以使用setRequestHeader()
,设定HTTP请求的头信息 - 2 (HEADERS_RECEIVED)
表示send()
方法已经执行,并且头信息和状态码已经收到。 - 3 (LOADING)
下载中;表示正在接收服务器传来的body部分的数据,responseText
属性已经包含部分数据。 - 4 (DONE)
表示服务器数据已经完全接收,或者本次接收已经失败了
2.3 解决IE缓存问题
问题:在一些浏览器中(IE),由于缓存机制的存在,ajax只会发送的第一次请求,剩余多次请求不会在发送给浏览器而是直接加载缓存中的数据。
解决方式:浏览器的缓存是根据url地址来记录的,所以我们只需要修改url地址即可避免缓存问题
xhr.open("get","/testAJAX?t="+Date.now())
2.4 实例代码
默认是异步的
// 提前声明,为了可以在其他作用域可以使用xhr.abort()
let xhr = null;
//标识变量
let isSending = false; // 是否正在发送AJAX请求
btn.addEventListener("click", function(){
//判断标识变量
if (isSending) x.abort();// 如果正在发送, 则取消该请求, 创建一个新的请求
//1. 创建对象
xhr = new XMLHttpRequest();
//修改 标识变量的值
isSending = true;
// 设置响应体数据的类型,后面可以自动转换
xhr.responseType = "json";
/*
// 超时设置 2s
xhr.timeout = 2000;
// 超时回调
xhr.ontimeout = function(){
alert("网络异常,请稍后重试!");
}
// 网络异常回调
xhr.onerror = function(){
alert("您的网络似乎出了一些问题!");
}
*/
//2. 初始化 设置请求方法和 url
xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');
//3. 发送
xhr.send();
//4. 事件绑定 处理服务端返回的结果
// readystate 是 xhr 对象中的属性, 表示状态 0 1 2 3 4
// change 改变
xhr.onreadystatechange = function(){
//判断 (服务端返回了所有的结果)
if(xhr.readyState === 4){
//判断响应状态码 200 404 403 401 500
// 2xx 成功
//修改标识变量
isSending = false;
if(xhr.status >= 200 && xhr.status < 300){
//处理结果 行 头 空行 体
//响应
// console.log(xhr.status);//状态码
// console.log(xhr.statusText);//状态字符串
// console.log(xhr.getAllResponseHeaders());//所有响应头
// console.log(xhr.response);//响应体
//设置 result 的文本
result.innerHTML = xhr.response;
}else{
}
}
}
});
同步
const xhr = new XMLHttpRequest()
// 同步请求不得设置 responseType和timeout
xhr.ontimeout = function () {
alert("网络异常,请稍后重试!")
}
// 网络异常回调
xhr.onerror = function () {
alert("您的网络似乎出了一些问题!")
}
// xhrReq.open(method, url, async) 第三个参数就是 是否是异步
xhr.open('post', 'https://sss.com?w_rid=6a507e3644f11685828e203925c28224&wts=1709401068', false)
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
xhr.withCredentials = true // 设置为本页面的请求cookie
// 发送请求
xhr.send(`msg[sender_uid]=292297687&msg[receiver_id]=647193094`)
// 同步请求的响应
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
const res = xhr.response && JSON.parse(xhr.response)
// console.log('xhr.response', res)
return res
} else {
}
}
三、jQuery中的AJAX
3.1 GET、POST 请求
$.get(url, [data], [callback], [dataType]);
$.post(url, [data], [callback], [dataType]);
- url
请求的URL地址 - data
请求携带的参数 - callback
载入成功时回调函数 - dataType
设置返回内容格式,xml、html、script、json、text、_default
3.2 $.ajax 通用请求
$.ajax({url:"", type:"", [data:{}], [dataType:""], [time:], [success:function], [error:function], [headers:{}]});
-
url
请求的URL地址 -
type
GET 或者 POST -
data
请求携带的参数 -
dataType
设置返回内容格式,xml、html、script、json、text、_default -
time
超时时间,单位 毫秒 -
success
成功的回调
-
error
失败的回调 -
headers
头信息
3.3 代码示例
// $.get();
$("button").eq(0).click(function () {
$.get("http://127.0.0.1:8000/jquery-server",
{ a: 100, b: 200 },
function (data) {
console.log(data);
},
"json");
});
// $.post();
$("button").eq(1).click(function () {
$.post("http://127.0.0.1:8000/jquery-server",
{ a: 100, b: 200 },
function (data) {
console.log(data);
});
});
// $.ajax
$("button").eq(2).click(function () {
$.ajax({
// url
url: "http://127.0.0.1:8000/jquery-server",
// 参数
data: { a: 100, b: 200 },
// 请求类型
type: "GET",
// 响应体结果
dataType: "json",
// 成功的回调
success: function (data) {
console.log(data);
},
// 超时时间
timeout: 2000,
// 失败的回调
error: function () {
console.log("出错啦!");
},
// 头信息
headers: {
c: 300,
d: 400
}
});
});
四、axios-AJAX
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 Node.js 中。
也是当下前端非常火热的AJAX工具库。
https://github.com/axios/axios
同jQuery使用AJAX类似
先引入
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
axios.get(url, {params:{}, headers:{}}).then(value=>{});
axios.post(url, {//请求体}, {params:{}, headers:{}}).then(value=>{});
axios({method:"", url:"", params:{}, headers:{}, data:{}}).then(response=>{});
axios.defaults.baseURL = "http://127.0.0.1:8000"
btns[0].onclick = function () {
// GET 请求
axios.get("/axios-server", {
// url 参数、请求行
params: {
id: 100,
vip: 6
},
// 请求头
headers: {
name: "Liwker",
age: 21
}
}).then(value => {
// promise 的回调
console.log(value);
});
}
// POST 请求
btns[1].onclick = function () {
axios.post("/axios-server", {
// 请求体
username: "admin",
password: "admin"
}, {
// 其他配置
// url参数
params: {
id: 200,
vip: 9
},
// 请求头
headers: {
height: 180,
weight: 180
},
});
}
// 通用方式
btns[2].onclick = function () {
axios({
// 默认是GET方式
method: "post",
// url
url: "/axios-server",
// url参数
params: {
vip: 10,
level: 30
},
// 头信息
headers: {
a: 100,
b: 200
},
// 请求体参数
data: {
username: "admin",
password: "admin"
}
}).then(response => {
console.log(response);
// 响应状态码
console.log(response.status);
// 响应状态字符串
console.log(response.statusText);
// 响应头信息
console.log(response.headers);
// 响应体
console.log(response.data);
});
}
五、fetch-AJAX
文档地址(https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope/fetch)
fetch() 也可以发起AJAX请求,和axios类似
fetcsh(url?参数, {method:"", headers:{}, body:""}).then(response=>{});
btn.onclick = function () {
fetch("http://127.0.0.1:8000/fetch-server?vip=10", {
// 请求方法
method: "post",
// 请求头
headers: {
name: "Liwker"
},
// 请求体
body: "username=admin&password=admin"
}).then(response => {
// console.log(response);
// return response.text();
return response.json();
}).then(response => {
console.log(response);
});
}
六、跨域
6.1 同源策略
同源策略(Same-Origin Policy)最早由 Netscape 公司提出,是浏览器的一种安全策略。
同源:协议、域名、端口号 必须完全相同。
违背同源策略就是跨域。
6.2 如何解决跨域
6.2.1 JSONP
-
JSONP是什么
JSONP (JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发出来,只支持get请求
-
JSONP 怎么工作的?
在网页有一些标签天生具有跨域能力,比如:img, link, iframe, script
JSONP就是利用script标签的跨域能力来发送请求的
-
JSONP的使用
// 创建handle函数
function handle(data) {
input.style.border = "1px solid red";
p.innerHTML = data.msg;
}
input.onblur = function () {
let username = this.value;
let scr = document.createElement("script");
scr.setAttribute("src", "http://127.0.0.1:8000/check-username");
document.body.appendChild(scr);
}
- jQuery中的JSONP
$('button').eq(0).click(function(){
$.getJSON('http://127.0.0.1:8000/jquery-jsonp-server?callback=?', function(data){
$('#result').html(`
名称: ${data.name}<br>
校区: ${data.city}
`)
});
});
jQuery 的 getJSON, 省去了 JSONP 中的 handle 函数定义
6.2.2 CORS
推荐阅读:
- http://www.ruanyifeng.com/blog/2016/04/cors.html
- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
-
CORS是什么?
CORS (Cross-Origin Resource Sharing), 跨域资源共享。CORS 是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持 get 和 post 等请求。跨域资源共享标准新增了一组 HTTP 首部字段(响应头),允许服务器声明哪些源站通过浏览器有权限访问哪些资源
-
CORS怎么工作的?
CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。
-
CORS的使用
主要是服务端的设置:
app.all("/cors-server", (request, response)=> {
// 设置响应头,设置允许跨域
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Method", "*");
response.send("Hello CORS!");
});