XMLHttpRequest的具体使用步骤会在get请求写法中进行展示,而post请求写法则会在post小点中展示。
XMLHttpRequest对象
XMLHttpRequest是浏览器内置构造函数,所有现代的浏览器都支持 XMLHttpRequest 对象。
XMLHttpRequest是什么
首先我们来看一下官方文档对这个对象的讲解:
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
- XMLHttpRequest简写XHR(xhr)
XMLHttpRequest对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest在 AJAX 编程中被大量使用。- 尽管名称如此,
XMLHttpRequest可以用于获取任何类型的数据,而不仅仅是 XML。它甚至支持 HTTP 以外的协议(包括 file:// 和 FTP),尽管可能受到更多出于安全等原因的限制。 》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
不通过js的http请求通常是通过form表单、script、link、img、video等标签完成。
总结一下:XMLHttpRequest对象功能
- 发出http请求。
- 用于获取任何类型数据。
- 支持http甚至是ftp协议。
所以我们可以使用
XMLHttpRequest对象向服务器发起请求,不再受限于原始的请求方式(form等标签)。
这里我展示一个简单的demo描述——阻止form提交请求并通过XMLHttpRequest对象来发起请求。
<form action="http://liyou.com:8080/login" method="POST" onsubmit='send(event)'>
<input name="name" type="text" placeholder="请输入名字">
<input name="pwd" type="password" placeholder="请输入密码">
<input type="submit" value="登录">
</form>
<script>
//这里编写了一个事件方法send(并且通过event的传参来实现对form标签默认的提交事件——http请求的阻止)
function send(event) {
console.log(event)
event.preventDefault();
let xhr = new XMLHttpRequest()
xhr.open('post', 'http://juejin.com:8080/login')
xhr.setRequestHeader('Context-type', 'application/x-www-form-urlencoded ');
xhr.onload = function () {
console.log(JSON.parse(xhr.responseText))
console.log(xhr)
}
xhr.send()
}
</script>
这里的open方法中的第二个参数是无效的只是示例。
使用XMLHttpRequest
XMLHttpRequest 对象提供了对 HTTP 协议的完全的访问,所以初学者很容易遇到通过使用XMLHttpRequest实现发送请求的场景。
所以我们需要学习具体的使用,不求全知,但求能在面试官和同事面前牛皮吹得起。
从上面的示例中我们可以看的出是对post请求的实现。
先是get请求的XHR步骤:
XMLHttpRequest本身是一个构造函数,我通过这个构造函数构造一个对象出来,这个对象就是XMLHttpRequest实例:(我们通常使用xhr作为简写以及XMLHttpRequest实例变量名)
let xhr = new XMLHttpRequest()
此时xhr作为XMLHttpRequest实例,继承了原型上封装好的方法,这些方法帮助我们去实现一个http请求,向服务器发送信息。
官方讲解的属性和方法集合
- open()——初始化一个请求
xhr.open('参数一,填写http请求类型', 'url值(这里添加get请求的字符串参数格式————name=xxx&pwd=xxx)')
补充可选参数:
- 参数三
async:布尔值,表示是否异步执行,默认true。浏览器大多不建议同步xhr执行。 - 参数四
user:用户名用于认证用途;默认为null。 - 参数五
password:密码用于认证用途,默认为null。
- setRequestHeader()——设置 HTTP 请求头
xhr.setRequestHeader('请求头参数名', '对应的可选参数')
- 该方法应该处于open和send方法之间,否则报错
- 如果多次执行setRequestHeader方法,不会覆盖,而是自动整合为多个值的请求头。
- 参数一header的大小写不敏感,字符正确即可。
- send()——发送请求
send方法应该在open和setRequestHeader等方法之后执行,建议放到最后执行
xhr.send('这里get请求不用,只有post请求使用')
如果是异步请求(默认为异步请求),则此方法会在请求发送后立即返回;如果是同步请求,则此方法直到响应到达后才会返回。XMLHttpRequest.send() 方法接受一个可选的参数,其作为请求主体;如果请求方法是 GET 或者 HEAD,则应将请求主体设置为 null。
- load事件——xhr请求成功完成时触发 load是事件,事件由特定动作进行触发,我们通过给load注册一个回调函数,来提供对该事件的处理。
xhr.onload = function () {
console.log(JSON.parse(xhr.responseText))
console.log(xhr)
}
我们最后来讲load事件中应该和可以使用哪些变量。这里展示完整get请求结构:
let id = document.querySelector('#id').value;
let xhr = new XMLHttpRequest()
xhr.open('get','http://juejinlogin.com/mysql_find?id='+id)
xhr.timeout = 5000;
xhr.onload=()=>{
console.log('接收到服务器响应');
console.log(JSON.parse(xhr.responseText));
//show(JSON.parse(xhr.responseText).user);
}
xhr.onerror=()=>{
console.log('请求失败')
}
xhr.send(null);
差异讲解post请求XHR步骤:
基本的差异都是围绕请求差异本身上,即get和post在参数上的差异。
- 差异一(请求方式)
open方法中参数一需要修改为post,表明初始化的请求为post请求。
xhr.open('post', 'url值(不加get请求的字符串参数后缀)')
- 差异二(请求实体)
post将数据放入请求报文body,通过send方法。send()方法的参数写法:
//send(body)
xhr.send("foo=bar&lorem=ipsum");
//官方例举的写法
// xhr.send('string');
// xhr.send(new Blob());
// xhr.send(new Int8Array());
// xhr.send({ form: 'data' });
// xhr.send(document);
- 差异三(头部字段)
因为我们请求实体携带的数据类型并不是只要和符合官方的格式,服务器就能识别,还需要通过头部字段content-type进行配合告诉服务器请求报文实体中携带的数据应该怎么解析:
xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded')
xhr.send("foo=bar&lorem=ipsum");
xhr.setRequestHeader('Content-type','application/json')//两种实体类型写法
xhr.send(json字符串);
更多的参数和写法可以查看 写篇文章之计网——(6)HTTP Content-type
- 完整post请求展示:
let name = document.querySelector('#addname').value;
let pwd = document.querySelector('#addpwd').value;
let xhr = new XMLHttpRequest()
xhr.open('post','http://juejinlogin.com/mysql_add')
xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded')
xhr.timeout = 5000;
xhr.onload=()=>{
console.log('接收到服务器响应');
console.log(JSON.parse(xhr.responseText));
}
xhr.onerror=()=>{
console.log('请求失败')
}
xhr.send(`name=${name}&password=${pwd}`);
如果body没有指定值,则默认值为
null,同时具体的数据写法要依据Content-type头部信息规范。(setRequestHeader方法设置)
客户端获取响应数据
承接load事件,我们已经确定服务器接收到请求并响应回来了。
实际上响应的是一个响应报文,我们需要获取里面的数据。
官方提供了三个属性接收数据,在load事件中我们可以放心使用。
- 使用代码示例:
//传输的字符串数据(文本),通常是JSON格式字符串,需要JSON方法解析成对象。
xhr.onload = function () {
console.log(JSON.parse(xhr.responseText))
console.log(JSON.parse(xhr.response))
console.log(JSON.parse(xhr.responseXML))
}
- xhr.response
返回一个 ArrayBuffer、Blob、Document,或 DOMString,具体是哪种类型取决于 XMLHttpRequest.responseType的值。其中包含整个响应实体(response entity body)。
- xhr.responseText
我们在load回调函数中直接操作responseText属性就可以满足开发需求。
返回一个 DOMString,该 DOMString 包含对请求的响应,如果请求未成功或尚未发送,则返回 null。
- xhr.responseXML
返回一个 Document,其中包含该请求的响应,如果请求未成功、尚未发送或不能被解析为 XML 或 HTML,则返回 null。
通常情况下response为DOMString格式时和responseText的值是一样的,此时responseXML就会是null,因为response为DOMString时说明Document为unll。
- 总结异同
》response和responseText默认值为空字符串
""(可以尝试在send方法之前打印观察) 而responseXML默认是null
》response和responseText只有当请求成功时,才能拿到正确值。
而responseXML要在请求成功情况下返回数据能够被正确解析。
其他属性、方法和事件补充
这里我不会全部列举,太多反而看着心累,我们挑些常用的来讲。
timeout属性——超时
一个无符号长整型(unsigned long)数字,表示该请求的最大请求时间(毫秒),若超出该时间,请求会自动终止。老生常谈的知识了,我们上代码示例吧
xhr.open('GET', '/server', true);
xhr.timeout = 2000; // 超时时间,单位是毫秒
getResponseHeader和getAllResponseHeaders方法——响应头
getAllResponseHeaders以字符串的形式返回所有用CRLF分隔的响应头(返回所有),如果没有收到响应,则返回 null。
getResponseHeader返回包含指定响应头的字符串(传参获取指定),如果响应尚未收到或响应中不存在该报头,则返回 null。
let headers = xhr.getAllResponseHeaders();
let header = xhr.getAllResponseHeaders("Content-Type");
ontimeout事件——超时
超时本身就会停止了请求,从而触发请求停止的事件,但是仍然有单独的超时事件。
xhr.ontimeout = function(e) {
console.error("Timeout!!")
}
onerror事件——失败
请求有成功就会有失败,当请求遇到错误时,将触发error 事件。
xhr.onerror = function(e) {
console.error("请求失败!!")
}
下一篇我们讲解XMLHttpRequest的意义以及和Ajax的关系