摘要:早在很多年前,我们发送网络请求都是通过刷新或者跳转页面来获取新的网络数据,从而达到渲染不同页面的需求,用户体验是很差的,直到 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:页面中设置的Cookie
  • Host: 发送请求页面所在的域
  • Referrer:发送请求的页面URL
  • User-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
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐