AJAX 全称为 Asynchronous JavaScript And XML,就是异步的 JS 和 XML。 通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。 AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。默认遵循同源策略。
XML 即可扩展标记语言。XML 和 HTML 类似,不同的是 HTML 中都是预定义标签,而 XML 中没有预定义标签, 全都是自定义标签,被设计用来传输和存储数据
比如说我有一个学生数据:
name = "孙悟空" ; age = 18 ; gender = "男" ;
用 XML 表示:
<student>
<name>孙悟空name>
<age>18age>
<gender>男gender>
student>
现在已经被 JSON 取代
用 JSON 表示:
{"name":"孙悟空","age":18,"gender":"男"}
Ajax 的优点
可以无需刷新页面而与服务器端进行通信。
允许你根据用户事件来更新部分页面内容。
Ajax 的缺点
//1,创建 XMLHttpRequest 对象
let xhr = new XMLHttpRequest()
// 设置响应体数据的类型(因为服务器只能传送字符串),后续接收的字符串自动处理了
//xhr.responseType = 'json';
// 手动对数据转化 let data = JSON.parse(xhr.response);
//2,初始化,设置请求信息
// xhr.open(method,url)
xhr.open('POST','http://127.0.0.1:8000/serve?a=1&b=2') //可设置请求参数
//xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); 设置请求头
//3,发送请求
//xhr.send(body) get请求不传送body参数,只有post请求使用
xhr.send('a=100&b=200&c=300+1234567') //设置请求体
//4,接收响应
// xhr.responseXML 接收XML格式的响应数据
// xhr.responseText 接收文本格式的响应数据
xhr.onreadystatechange = function(){
if(xhr.readyState===4){ //响应状态码
if(xhr.status>=200 && xhr.status<300){
console.log(xhr.response)//响应体
}
}
}
即XMLHttpRequest.readyState属性
0 UNSENT : XMLHttpRequest 代理已被创建, 但尚未调用 open() 方法。
1 OPENED : open() 方法已经被触发。在这个状态中,可以通过 setRequestHeader() 方法来设置请求的头部, 可以调用 send()方法来发起请求。
2 HEADERS_RECEIVED : send() 方法已经被调用,响应头也已经被接收。
3 LOADING : 响应体部分正在被接收。如果 responseType 属性是“text”或空字符串, responseText 将会在载入的过程中拥有部分响应数据。
4 DONE : 请求操作已经完成。这意味着数据传输已经彻底完成或失败。
const xhr = new XMLHttpRequest();
//超时设置 2s ,超过2s没收到系统回复即取消请求
xhr.timeout = 2000;
//超时回调 ,超时后启动
xhr.ontimeout = function(){
alert("网络异常, 请稍后重试!!");
}
//网络异常回调
xhr.onerror = function(){
alert("你的网络似乎出了一些问题!");
}
...
XMLHttpRequest.abort() 方法可以取消发送的请求
当重复点击发起重复请求时,为避免浪费资源,启动防抖,即取消前面的请求,只保留最新的请求
let flag = false; // 是否正在发送AJAX请求
btns[0].onclick = function(){
//判断标识变量
if(flag) x.abort(); //如果正在发送, 则取消该请求, 创建一个新的请求
x = new XMLHttpRequest();
flag = true; //修改 标识变量的值
x.open("GET",'http://127.0.0.1:8000/serve');
x.send();
x.onreadystatechange = function(){
if(x.readyState === 4){
//修改标识变量
isSending = false;
...
}
}
}
问题:在一些浏览器中(IE),由于缓存机制的存在,ajax 只会发送的第一次请求, 剩余多次请求不会在发送给浏览器而是直接加载缓存中的数据。
解决方式:浏览器的缓存是根据 url 地址来记录的,所以我们只需要修改 url 地址即可避免缓存问题
xhr.open("get","/testAJAX?t="+Date.now());
//以下是引入axios后的用法,只展示使用部分
//配置 baseURL,即下面所有路径默认前面加上此url
axios.defaults.baseURL = 'http://127.0.0.1:8000';
//axios发送请求的示例,常用 axios(config),axios(url[, config])
axios({
//请求方法 默认get
method : 'POST',
//url
url: '/axios-server',
//url参数
params: {pa: 'pa'},
//请求头信息,若是自写头,需服务器提供权限
headers:{head: 'head'},
//请求体参数
data: {
username: 'admin',password: 'admin'}
}).then(response=>{
console.log(response.status); //响应状态码
console.log(response.statusText ; //响应状态字符串
console.log(response.headers); //响应头信息
console.log(response.data); //响应体
})
//axios发送get请求的示例 axios.get(url[, config])
axios.get('/axios-get-server', {
params: {pa: 'pa'},
headers: {head: 'head'}
}).then(value => {
//对返回数据的处理
console.log(value);
});
//axios发送post请求的示例 axios.post(url[, data[, config]])
axios.post('/axios-post-server', {
//请求体内容
username: 'admin',password: 'admin'
}, {
params: {pa: 'pa'},
headers: {head: 'head'}
}).then(value => {
console.log(value);
})
fetch('http://127.0.0.1:8000/fetch-server?k=1', {
//请求方法
method: 'POST',
//请求头
headers:{head: 'head'},
//请求体
body: 'username=admin&password=admin'
}).then(response => {
// 此时形参response是Response对象
return response.json();
//该方法可读取 Response 对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 JSON 格式的 Promise 对象。
}).then(response=>{
// 此时形参response是Promise对象的值
console.log(response);
});
ajax 属 js 原生,基于XHR(即XMLHttpRequest对象)进行开发,XHR 结构不清晰,容易生成回调地狱。
fetch方法属于原生 js,脱离了XHR,支持Promise,但兼容性较差,和有其他问题。
目前一般使用axios,本质还是 ajax,即XHR,基于 Promise 进行封装,既解决回调地狱问题,又能很好地支持各个浏览器。
同源策略(Same-Origin Policy)最早由 Netscape 公司提出,是浏览器的一种安全策略。同源即 协议、域名、端口 必须完全相同。浏览器出于安全方面的考虑,只允许本域名下的接口交互,不同源的客户端脚本,在没有明确授权的情况下,不能读取对方的资源。主要用来防止CSRF(跨站请求伪造)攻击。
违返浏览器的同源策略就是跨域。 解决同源策略的方案有:jsonp,iframe,CORS,webscoket,代理服务器等。
JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发出来,只支持 get 请求。在网页有一些标签天生具有跨域能力,比如:img link iframe script。 JSONP 就是利用 script 标签的跨域能力来发送请求的。
JSONP 的使用:
//1.动态的创建一个 script 标签
let script = document.createElement("script");
//2.设置 script 的 src 属性,只要服务器中返回的是JS代码即可
script.src = "http://localhost:8000/testAJAX?callback=abc"
//3.将 script 添加到 dom 中
document.body.appendChild(script);
CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS 是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持 get 和 post 请求。跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源
具体操作:CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应 以后就会对响应放行。主要是服务器端的设置:
//下面的代码在node.js的express内使用
router.get("/testAJAX" , function (request , response) {
//通过 response 来设置响应头,来允许跨域请求
//response.set("Access-Control-Allow-Origin","http://127.0.0.1:3000");
response.setHeader("Access-Control-Allow-Origin","*"); //随便跨域
response.setHeader('Access-Control-Allow-Headers', '*') //随便请求头
})