XMLHttpRequest 运作机制
function GetWebData(URL){
/**
* 1: 新建 XMLHttpRequest 请求对象
*/
let xhr = new XMLHttpRequest()
/**
* 2: 注册相关事件回调处理函数
*/
xhr.onreadystatechange = function () {
switch(xhr.readyState){
case 0: // 请求未初始化
console.log(" 请求未初始化 ")
break;
case 1://OPENED
console.log("OPENED")
break;
case 2://HEADERS_RECEIVED
console.log("HEADERS_RECEIVED")
break;
case 3://LOADING
console.log("LOADING")
break;
case 4://DONE
if(this.status == 200||this.status == 304){
console.log(this.responseText);
}
console.log("DONE")
break;
}
}
xhr.ontimeout = function(e) { console.log('ontimeout') }
xhr.onerror = function(e) { console.log('onerror') }
/**
* 3: 打开请求
*/
xhr.open('Get', URL, true);// 创建一个 Get 请求, 采用异步
/**
* 4: 配置参数
*/
xhr.timeout = 3000 // 设置 xhr 请求的超时时间
xhr.responseType = "text" // 设置响应返回的数据格式
xhr.setRequestHeader("X_TEST","time.geekbang")
/**
* 5: 发送请求
*/
xhr.send();
}
1. 创建 XMLHttpRequest 对象
当执行到let xhr = new XMLHttpRequest()后,JavaScript 会创建一个 XMLHttpRequest 对象xhr,用来执行实际的网络请求操作。
2. 为 xhr 对象注册回调函数
因为网络请求比较耗时,所以要注册回调函数,这样后台任务执行完成之后就会通过调用回调函数来告诉其执行结果。
XMLHttpRequest 的回调函数主要有下面几种:
- ontimeout,用来监控超时请求,如果后台请求超时了,该函数会被调用;
- onerror,用来监控出错信息,如果后台请求出错了,该函数会被调用;
- onreadystatechange,用来监控后台请求过程中的状态,比如可以监控到 HTTP 头加载完成的消息、HTTP 响应体消息以及数据加载完成的消息等。
3. 配置基础的请求信息
注册好回调事件之后,接下来就需要配置基础的请求信息了,首先要通过 open 接口配置一些基础的请求信息,包括请求的地址、请求方法(是 get 还是 post)和请求方式(同步还是异步请求)。
然后通过 xhr 内部属性类配置一些其他可选的请求信息,通过xhr.timeout = 3000来配置超时时间,也就是说如果请求超过 3000毫秒还没有响应,那么这次请求就被判断为失败了。
还可以通过xhr.responseType = "text"来配置服务器返回的格式,将服务器返回的数据自动转换为自己想要的格式,如果将 responseType 的值设置为 json,那么系统会自动将服务器返回的数据转换为 JavaScript 对象格式。
还可以通过 xhr.setRequestHeader 来添加自己专用的请求头属性。
4. 发起请求
切准备就绪之后,就可以调用xhr.send来发起网络请求了。渲染进程会将请求发送给网络进程,然后网络进程负责资源的下载,等网络进程接收到数据之后,就会利用 IPC 来通知渲染进程;渲染进程接收到消息之后,会将 xhr 的回调函数封装成任务并添加到消息队列中,等主线程循环系统执行到该任务的时候,就会根据相关的状态来调用对应的回调函数。
- 如果网络请求出错了,就会执行 xhr.onerror;
- 如果超时了,就会执行 xhr.ontimeout;
- 如果是正常的数据接收,就会执行 onreadystatechange 来反馈相应的状态。
XMLHttpRequest 使用过程中的安全问题
1. 跨域问题
比如在极客邦的官网使用 XMLHttpRequest 请求极客时间的页面内容,由于极客邦的官网是www.geekbang.org,极客时间的官网是time.geekbang.org,它们不是同一个源,所以就涉及到了跨域(在 A 站点中去访问不同源的 B 站点的内容)。默认情况下,跨域请求是不被允许的。因为 www.geekbang.org 和 time.geekbang.com 不属于一个域,所以以上访问就属于跨域访问了,这次访问失败就是由于跨域问题导致的。
2. HTTPS 混合内容的问题
HTTPS 混合内容是 HTTPS 页面中包含了不符合 HTTPS 安全要求的内容,比如包含了 HTTP 资源,通过 HTTP 加载的图像、视频、样式表、脚本等,都属于混合内容。
通常,如果 HTTPS 请求页面中使用混合内容,浏览器会针对 HTTPS 混合内容显示警告,用来向用户表明此 HTTPS 页面包含不安全的资源。