让大家都能理解 XMLHttpRequest
XMLHttpRequest 是一个 JavaScript 对象,它能够在浏览器和 Web 服务器之间发送和接收数据。即使在从 Web 服务器读取了所有数据之后,XMLHttpRequest 仍然可以发送和接收数据,从而实现不重新加载页面就能够重写页面内容的功能。在当今的 Web 服务中,使用 XMLHttpRequest 发送和接收数据是非常必要的。尽管现在使用XMLHttpRequest 直接与Web服务器收发数据的机会不多,大多数情况下都是使用 axios(底层使用 XMLHttpRequest)和 fetch 函数。但是,理解 XMLHttpRequest 对于理解这些技术仍然非常重要,因此我们应该深入了解它。
- 让大家都能理解 XMLHttpRequest
- 1 XMLHttpRequest使用
- 2 XMLHttpRequest 处理流程
- 3 onreadystatechange 事件
- 4 接收 JSON 数据
- 5 响应类型
- 6 XMLHttpRequest其他事件
- 7 FormData 请求
1 XMLHttpRequest使用
以下是使用 XMLHttpRequest 的 JavaScript 代码,它应该写在脚本标签中:
<script>// (1)XMLHttpRequest对象创建var xmlHttpRequest = new XMLHttpRequest();// (2)onreadystatechange监听请求的状态xmlHttpRequest.onreadystatechange = function(){ if(this.readyState == 4 && this.status == 200){ console.log(this.responseText); }}// (3)HTTP通过GET服务路径与服务器进行通信xmlHttpRequest.open( 'GET', 'https://jsonplaceholder.typicode.com/users/1', true);// (4)HTTP中发生信息xmlHttpRequest.send();</script>
我们可以使用 https://jsonplaceholder.typicode.com/ URL 来进行测试,它是一个公共的网络测试资源地址,专门用于测试。如果您不想搭建自己的服务器,可以尝试使用它来进行 Ajax 路径测试。
2 XMLHttpRequest 处理流程
(1) 创建一个XMLHttpRequest对象
var xmlHttpRequest = new XMLHttpRequest();
创建 XMLHttpRequest 实例,使用该实例可以在浏览器和服务器之间进行通信。
(2)用onreadystatechange事件监听请求状态
xmlHttpRequest.onreadystatechange = function(){ if(this.readyState == 4 && this.status == 200){ console.log(this.responseText); }}
可以使用 onreadystatechange 事件来监视 XMLHttpRequest 处理状态的变化。该事件用于监视状态的变化,以便可以检测来自服务器的响应(即接收到的数据)何时完成。此外,还可以通过确认响应的 HTTP 状态代码是否为 200,来确定请求是否成功。
readyState 被分配一个从 0 到 4 的数字,代表处理的状态,其中 4 代表请求处理完成。如果 readyState 为 4,状态码为 200,则可以使用 console.log 命令打印接收到的数据。
由于 XMLHttpRequest 与服务器进行异步通信,与等待同步处理完成不同,您不知道何时处理完成。因此,我们需要使用 onreadystatechange 事件来监视处理状态,并采取适当的措施。
使用该事件,可以在请求的处理过程中多次检查 readyState 的值,并据此采取必要的操作,以确保在处理完成时能够得到所需的结果。
(3)指定HTTP GET方法和访问位置
xmlHttpRequest.open( 'GET', 'https://jsonplaceholder.typicode.com/users/1', true);
第三个参数 true 是异步设置。如果异步则设置为 true,如果同步则设置为 false。
XMLHttpRequest.open('HTTP类型','URL',['async',user,password])
如果要进行异步通信,则应将 async 参数设置为 true,如果要进行同步通信,则应将其设置为 false。在使用 open 方法时,还可以指定用户和密码,以进行基本身份验证。
(4) 发送HTTP请求
xmlHttpRequest.send();
发送请求到服务器然后等待服务器的响应。我们可以使用 (2) 中的事件来检查服务器的响应是否完成。
3 onreadystatechange 事件
在ajax请求的时候每当处理状态发生变化时,都会产生 readystatechange 事件,以便代码可以相应地处理变化。当前状态可以通过 readyState 属性进行判断。readyState 属性被分配了 0 到 4 之间的值,并且含义因数字而异。
- readyState=0 : status=UNSENT: 初始状态(实例创建)
- readyState=1 : status=OPENED: 打开方法执行
- readyState=2 : status=HEADERS_RECEIVED: 收到响应头
- readyState=3 : Status=LOADING: 正在接收数据
- readyState=4 : status=DONE: 请求完成
使用下面的代码检查每次进程状态更改时是否实际触发了 onreadystatechange 事件。除了 onreadystatechange 事件外,其余的代码与前面解释的代码相同。
xmlHttpRequest.onreadystatechange = function(){ if(this.readyState == 0){ console.log('UNSENT:初始状态') } if(this.readyState == 1){ console.log('OPENED: 打开方法执行') } if(this.readyState == 2){ console.log('HEADERS_RECEIVED:收到响应头') } if(this.readyState == 3){ console.log('LOADING:正在接收数据') } if(this.readyState == 4){ console.log('DONE: 请求完成') }}
4 接收 JSON 数据
在与服务器进行通信时,大多数情况下数据都是以 JSON 格式发送的。我们可以将服务器返回的数据转换为 JSON 格式。请注意,服务器端的处理因环境而异,返回的数据格式有所不同。但是我们大多数情况使用 Spring Boot 作为服务端,因此返回的数组会自动转换为 JSON 格式。
xmlHttpRequest.onreadystatechange = function(){ if(this.readyState == 4 && this.status == 200){ user = JSON.parse(this.responseText); console.log(user) }}
如果this.responseText
返回的数据是以字符串形式的 JSON 数据传输的,我们需要使用JSON.parse()
方法将其解析成一个 JavaScript 对象。如果不进行转换,该数据可能会被解释为 undefined。
5 响应类型
如果你设置了 Response Type 为 JSON,那么可以直接获取响应数据的格式。因此,不需要再运行 JSON.parse 将其转换为对象。不过,需要注意的是,在获取值时,应该使用 response 属性,而不是 responseText。
var xmlHttpRequest = new XMLHttpRequest();xmlHttpRequest.responseType = 'json';xmlHttpRequest.onreadystatechange = function(){ if(this.readyState == 4 && this.status == 200){ //responseType = 'json' 不能使用this.responseText //直接使用 response user = this.response; console.log(user) }}
使用 getAllResponseHeaders() 检查来自服务器的响应标头信息。
var xmlHttpRequest = new XMLHttpRequest();xmlHttpRequest.responseType = 'json';xmlHttpRequest.onreadystatechange = function(){ if(this.readyState == 4 && this.status == 200){ //responseType = 'json' 不能使用this.responseText //直接使用 response user = this.response; console.log(user); console.log(this.getAllResponseHeaders()); }}
6 XMLHttpRequest其他事件
我们使用 onreadystatechange 事件来检查处理状态,除了 onreadystatechange 事件之外,还有以下事件可以使用。
- onloadstart :请求开始时
- onprogress :定期运行,直到请求完成。也可以检查接收到的数据。
- onabort :当请求被 abort 方法中止时
- onerror : 当请求发生错误时
- onload :请求完成时
- ontimeout :请求超时时
设置以下 6 个事件并检查它们是被执行正常工作。
xmlHttpRequest.onloadstart = function(){ console.log('onloadstart请求开始时');};xmlHttpRequest.onprogress = function(){ console.log('onprogress事件');};xmlHttpRequest.onload = function(){ console.log('onload事件');};xmlHttpRequest.onabort = function(){ console.log('onabort事件');};xmlHttpRequest.onerror = function(){ console.log('onerror事件');};xmlHttpRequest.ontimeout = function(){ console.log('ontimeout事件');};
我们可以看到浏览器GET请求成功完成后只执行了以下3个事件。
onloadstart请求开始时onprogress事件onload事件
abort 事件触发条件,只有在XMLHttpRequest在代码中设置abort方法,并且使用它。发送数据后立即执行 abort 方法,才会执行abort 事件。
xmlHttpRequest.send();xmlHttpRequest.abort();
这样才可以看到在启动请求的 onloadstart 之后触发了 onabort 事件。
接下样我们看看超时事件 ontimeout 触发条件。设置请求超时。由于单位是毫秒,如果请求后2000(=2秒)服务器没有响应,就会执行事件。
xmlHttpRequest.timeout = 2000
onerror 事件 触发条件是,访问了服务器端一个不存在的IP地址,onerror 事件才会发生。
xmlHttpRequest.open('GET','http://127.0.0.100',true);
我发现可以在 onerror 事件中检查网络级错误。当收到 404 错误,这意味着你能够与服务器通信,但是页面不存在。在这种情况下,我们可以在执行的 onload 事件中进行检查。当程序执行 onload 事件时,也会显示HTTP状态码,返回状态码404和Not Found404。
xmlHttpRequest.onload = function(){ console.log('onload事件'); //状态 console.log(this.status);};
我们可以使用HTTP状态代码来判断是否发生了HTTP级别的错误。如果状态代码不是正常的200,就可以终止程序的运行;否则,程序可以继续运行。我们通常会使用它来处理 404 以及服务器的 Eroro 500错误。
xmlHttpRequest.onload = function(){ if(this.status != 200){ console.log(this.status + ':程序终止运行。'); }else{ console.log(this.status + '正常运行。'); }};
7 FormData 请求
下面是用于向服务器异步发送数据的 JavaScript 代码。
<script> // (1)XMLHttpRequest创建实例 var xmlHttpRequest = new XMLHttpRequest(); // (2)HTTP的POST请求 xmlHttpRequest.open('POST','/api/onsave',true); // (3)数据发送的格式类型 xmlHttpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); // (4)HTTP发送的数据 xmlHttpRequest.send('id=2&name=zht');</script>
步骤(3)的设置是指定要发送的数据的格式。这次发送数据的格式是key1=value1&key2=value2,所以Content-Type要设置成application/x-www-form-urlencoded。如果不指定数据格式,在服务器端可能无法正常的接收数据。
大多数的时候我们会使用 FormData 对象发送数据。让我们看看FormData 是如何发送数据的。
var xmlHttpRequest = new XMLHttpRequest();var formData = new FormData();formData.append("id", 3);formData.append("name","zht");xmlHttpRequest.open('POST','/api/onsave',true);xmlHttpRequest.send(formData);
代码中使用 FormData 的 append 方法添加要发送的数据。此外,使用 FormData发送数据在代码中不需要设置内容类型setRequestHeader 。
通过下面的例子让我们看看在html代码中如何使用FormData将form数据发送到服务端的。
<form name="user"> Id:<input type="text" name="id"><br> 名称:<input type="text" name="name"><br> <input type="submit" onclick="sendPost();return false;">添加</button></form>
创建 sendPost
函数,该函数内部使用 document.forms.user
方法将表单的内容放入 FormData
对象中。通过发送 FormData
对象,将输入表单的内容发送到服务器(使用 POST
请求方式)。
function sendPost(){ var xmlHttpRequest = new XMLHttpRequest(); var formData = new FormData(document.forms.user); xmlHttpRequest.open('POST','/api/onsave',true); xmlHttpRequest.send(formData);}