早在很多年前,我们发送网络请求都是通过刷新或者跳转页面来获取新的网络数据,从而达到渲染不同页面的需求,用户体验是很差的,直到 ajax 横空出生,才解决了这个问题,不需要刷新页面便可以获取请求数据,这也是后来前后端分离的重要根源,大大的提高了网页性能,优化了用户体验。
而 ajax 的核心就是我们今天要学的的原生请求,**XMLHttpRequest**对象。
一. XMLHttpRequer 对象
创建: 通过 new 来创建。
1. 使用 XHR
open
: 接收三个参数,分别为请求类型,请求的URL,请求是否异步,该方法为发送请求做好准备send
: 接收一个参数,请求体发送的内容,如果不发送,必须写入null,该方法开始发送请求status
: 相应的 HTTP 状态码,当位于 200~300 或者 等于 304 时,说明响应成功返回。responseText
: 作为响应体返回的文本statuesText
: 响应 HTTP 的状态描述abort
: 该方法用来取消异步请求,会停止触发事件,调用该方法后应该取消对XHR对象的引用,不要重用XHR对象。onreadystatechange
: 用来监听请求位于哪个阶段,该方法应该在open前调用,该事件不会接收到event对象readyState
: 表示当前请求位于哪个阶段
0: 未初始化,尚未调用 open
1:已经调用open,尚未调用 send
2:已经送,已经调用send,未收到响应
3:接收中,已经收到部分响应
4:完成,接收到所有响应
let xhr = new XMLHttpRequest(); // 创建XMLHttpRequest 实例
xhr.open("get", "http://127.0.0.1:3000/index", false); //设置为同步get请求
xhr.send(null); // 开始发送请求,并且阻塞后续代码执行,直到拿到响应
if((xhr.status >=200 && xhr.status <300) || xhr.status == 304){
console.log(xhr.responseText) // 检验状态码
}else{
console.log('请求失败')
}
使用readyState:
每次该值的改变,都会触发readystatechange 事件,因此我们可以在不同阶段执行不同操作
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){ // 监听请求完成
if((xhr.status >=200 && xhr.status <300) || xhr.status == 304){
console.log(xhr.responseText)
}else{
console.log('请求失败')
}
}
}
xhr.open("get", "http://127.0.0.1:3000/index", true); // 异步请求
xhr.send(null);
2. HTTP 头部
① 默认头部信息
每个HTTP 请求和响应都会携带头部信息,我们来看一下默认的一些请求头部
Accept
: 浏览器可以处理的内容类型Accept-Charset
:浏览器可以显示的字符集Accept-Encoding
: 浏览器可以压缩的编码类型Connection
: 浏览器与服务的连接类型Cookie
:页面中设置的CookieHost
: 发送请求页面所在的域Referrer
:发送请求的页面URLUser-Agent
: 浏览器的用户代理字符串
②设置自定义头部信息
setRequestHeader()
: 该方法接收两个参数,头部字段的名称和值,该方法必须在open之后,send 之前调用getResponseHeader()
: 从XHR对象获取响应头部,只需要传入获取头部的名称即可getAllResponeHeaders()
: 获取所有响应头信息
3. GET 请求
用于向服务器查询某些信息,数据直接显示在url中
① 传参
需要将信息编码后,添加到URL末尾,用 ? 隔开,各个参数用&隔开,参数的键值用=隔开
function addURLParam(url, name, value){
const code = url.indexOf('?') == -1 ? '?' : '&';
url += code;
url += (encodeURIComponent(name) + '=' + encodeURIComponent(value))
return url;
}
4. POST 请求
用于向服务器发送应该保存的数据,该数据在请求体中传输,只需要将要发送的数据写入send方法中即可。
let btn = document.getElementById('btn')
btn.onclick = function(){
const xhr = new XMLHttpRequest();
xhr.open('post', '/post', false);
xhr.send('sssss')
}
5. XMLHttpRequest 标准2
① FormData 类型
用于将表单数据序列化,可以使用post请求模拟表单提交,使用该方法默认将请求类型,设置为表单格式。
xhr.setRequestHeader('Content-Type', "application/x-www-form-urlencoded")
实例反法:
append: 接收两个参数,通过键值对的方式,将数据填入表单
let form = new FormData();
form.append('age','12')
form.append('name', '石头山')
也可以在构造函数中传入一个表单。
let form = new FormData(document.forms[0);
② 超时
用于表示发送请求后需要等待多少毫秒,如果响应不成功就中断请求
timeout: 用来设置超时时间,如果超时则会触发 ontimeout 事件,同时 readyState 的状态也会变成 4,同时调用 onreadystatechange 事件,并且超时之后访问 statues 属性会出错
切记,同步请求不能设置超时
xhr.open('post', '/post', true); // 此处只能为 true
xhr.timeout = 1000;
xhr.ontimeout = function(){
console.log('请求超时')
}
xhr.send(null)
二. 进度事件
loadstart
: 在接收到响应的第一个字节时触发progress
: 在接收响应期间反复触发error
:在请求出错时触发abort
:在调用 abort()终止连接时触发load
: 在成功接收完响应时触发loadend
:在通信完成时,在error,abort,load之后触发
1. load事件
该属性用来题代 readystatechange 事件,但是有一个问题,只有从服务器收到响应,无论状态码是什么,都会触发该事件,因此还需要检验状态码来确保数据有效。
const xhr = new XMLHttpRequest();
xhr.open('get', '/index', true);
xhr.onload = function(){
if((xhr.status >= 200 && xhr.status<300) || xhr.status === 304){
console.log(xhr.responseText,'ss11');
}else{
console.log('请求错误')
}
}
xhr.send(null)
2. progress 事件
在数据接收期间,该事件反复触发,该事件对象有三个属性
lengthComputable
: 表示进度信息是否可用position
:接收到的字节数totalSize
: 是响应体头部 Content-Length 的总字节数
xhr.onprogress = function(event) {
if(event.lengthComputable){
console.log(event.total, event.position)
}
}
三. 跨资源共享
1. 跨域安全策略
默认情况XHR只能访问与发起请求的页面在同一个域内的资源。
- 原生跨域:给open传入一个绝对路径则跨源访问
- 限制:
1.不能是使用setRequestHeader() 设置自定义头部
2.不能发送和接收cookie
3.getAllResponseHeaders() 方法始终返回 空字符串
因此,在访问本地资源时使用相对路径,访问远程资源时使用绝对路径
2. 预检请求
通过该机制,允许使用自定义头部,除GET和POST外的方法,在发送请求时先发送一个预检请求,这个请求使用OPTIONS方法发送以下头部。
Origin
:与简单请求相同Access-Control-Request-Method
: 请求希望使用的方法Access-Control-Request-Headers
: 自定义头部列表
服务器可以确定是否允许这种类型的请求。会在响应中发送如下头部
Access-Control-Allow-Origin
: 允许的同源Access-Control-Allow-Methods
: 允许的方法Access-Control-Allow-Headers
: 允许的自定义头部Access-Control-Allow-Max-Age
: 缓存预检请求的秒数
预检请求返回后,会缓存一段时间,在这段时间内再次访问不需要预检。
3. 凭据请求
默认情况下,跨源请求不提供凭据,cookie,http认证,SSl证书。可以通过将withCredentials 属性设置为true来表明请求会发送凭证。
如果服务器允许携带,则在响应头部添加
Access-Control-Allow-Credentials: true.
四. 替代性跨源技术
1. 图片探测
2. JSONP
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。