总结
我在成长过程中也是一路摸爬滚打,没有任何人的指点,所以走的很艰难。例如在大三的时候,如果有个学长可以阶段性的指点一二,如果有已经工作的师兄可以告诉我工作上需要什么,我应该前面的三年可以缩短一半;后来去面试bat,失败了有5、6次,每次也不知道具体是什么原因,都是靠面试回忆去猜测可能是哪方面的问题,回来学习和完善,当你真正去招人的时候,你就会知道面试记录是多么重要,面试官可以从面试记录里看到你的成长,总是去面试,总是没有成长,就会被定义为缺乏潜力。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
既然Ajax涉及到前后端的数据交互,那么我们就先来简单的看一下几种类型的状态码,如下表:
| 状态码 | 含义 |
| — | — |
| 100 ~ 199 | 连接继续 |
| 200 ~ 299 | 各种成功的请求 |
| 300 ~ 399 | 重定向 |
| 400 ~ 499 | 客户端错误 |
| 500 ~ 599 | 服务端错误 |
在使用xhr之前,我们要创建一个xhr的实例对象
let xhr = new XMLHttpRequest()
然后再调用xhr对象上的 open()
方法,表示创建一个请求。
open()
方法接收三个参数:
-
第一个参数: 请求的类型(例如get 、post)
-
第二个参数: 请求的URL
-
第三个参数: 是否异步发送请求(默认为true)
// 创建了一个Ajax请求
xhr.open(‘get’, ‘example.php’, ‘true’)
光调用了 open()
方法还不够,它只是创建了一个请求,但还没有发送请求,因此我们还要调用xhr对象上的另一个方法,即 send()
方法,表示将请求发送给目标URL
send()
方法接收一个参数:
- 第一个参数: 作为请求主体发送的数据(例如post请求携带的数据)
// 我们上面创建的是get请求,因此send()方法无需传参
xhr.send()
请求发送出去后,客户端需要接收服务器响应回来的数据,xhr对象中有一些属性,它们存储着服务端返回来的一些数据信息,如下表所示
| 属性名 | 含义 |
| — | — |
| responseText | 服务端返回的文本信息 |
| responseXML | 服务端返回的XML DOM文档 |
| status | HTTP状态码 |
| statusText | HTTP状态码说明 |
| readyState | xhr对象的请求响应阶段 |
既然我们要获取服务端返回的数据,我们就要知道服务端是何时返回数据的,这就可以通过上面表格中的 readyState
属性来判断了
readyState
属性一共有5个值,分别表示不同的请求响应阶段:
-
0: 还未创建请求,即未调用
open()
方法 -
1: 已调用
open()
方法,但未发送send()
方法 -
2: 已调用
send()
方法,但未接收到响应 -
3: 已接收到部分响应
-
4: 已接收到全部的响应
同时,xhr对象可以绑定一个 readystatechange
事件,每当 readyState
属性发生改变,都会触发该事件,因此,该事件在一次请求中会被多次触发
xhr.onreadystatechange = function() {
console.log(‘readyState属性发生改变了’)
}
所以,我们可以在 readystatechange
事件中判断一下 readyState
属性是否为 4
,即是否已经接收所有的响应,然后还可以再继续判断一下 status
属性,看看状态码是否为 200
,当上述都成立了,我们再去 responseText
属性 或 responseXML
属性中获取响应数据
xhr.onreadystatechange = function() {
// 判断是否已接收所有响应
if(xhr.readyState === 4) {
// 判断状态码是否为200
if(xhr.status === 200) {
console.log(xhr.responseText)
}
}
}
上面也讲解了Ajax请求的简单应用,同时也是拿 get
请求来举得例子,因此这里我就不多做说明,唯一要讲的就是,get请求所携带的数据是明文的,大小只有4k左右,而且它是写在URL的 ?
后面的,例如这样 example.php?query=4&em=0
,所以若是我们要在发送get请求时携带数据,只需要在调用 open()
方法时,将数据写在第二个参数的URL的 ?
后面即可
直接来写一次完整的 get
请求,代码如下:
let xhr = new XMLHttpRequest()
xhr.open(‘get’, ‘example.php?query=4&em=0’)
xhr.send()
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if(xhr.status === 200){
console.log(xhr.responseText);
}
}
}
发送post请求的过程几乎和get请求一样,唯一不一样的是数据的传递。大家都知道post请求的数据是放在请求体中的,因此我们需要调用xhr对象上的 setRequestHeader()
方法来模仿表单提交时的内容类型
该方法传入的参数比较固定,代码如下
xhr.setRequestHeader(‘Content-Type’, ‘application/x-www-form-urlencoded’)
然后我们上面也说过,send()
方法接收的一个参数是请求主体发送的数据,所以我们的post请求要发送的数据就要作为该方法的参数,代码如下:
xhr.send(‘query=4&em=0’)
那我们来看一次完整的post请求是怎么样的吧,代码如下:
let xhr = new XMLHttpRequest()
xhr.open(‘post’, ‘example.php’)
xhr.setRequestHeader(‘Content-Type’, ‘application/x-www-form-urlencoded’)
xhr.send(‘query=4&em=0’)
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if(xhr.status === 200){
console.log(xhr.responseText);
}
}
}
=================================================================
文章开头提到,JQuery早已对Ajax请求进行了成熟的封装,所以我们可以借鉴它,甚至尽可能地去模仿它进行封装,在这之前,我们得先了解JQuery中Ajax的使用
这里我找来了几段使用JQuery发送Ajax请求的代码,如下所示:
- 发送get请求
$.get(‘example.php’, {query: 4, em: 0}, function(data, status, xhr) {
console.log(`
返回的数据为${data}
返回的状态为${status}
返回xhr对象为${xhr}
`)
}, ‘json’)
这段代码发送了一个 get
请求,携带的参数有 query
值为 4
、em
值为 0
,规定返回的数据类型为 json
,同时设定了一个回调函数用于接收请求返回的数据、状态和xhr对象
- 发送post请求
$.post(‘example.php’, {query: 4, em: 0}, function(data, status, xhr) {
console.log(`
返回的数据为${data}
返回的状态为${status}
返回xhr对象为${xhr}
`)
}, ‘json’)
这段代码发送了一个 post
请求,携带的参数有 query
值为 4
、em
值为 0
,规定返回的数据类型为 json
,同时设定了一个回调函数用于接收请求返回的数据、状态和xhr对象
- 综合方法
// 该方法既可以发送get请求又可以发送post请求
$.ajax({
url: ‘example.php’, // 请求的URL
type: ‘get’, //请求类型,若为post,则表示发送post请求
data: {query: 4, em: 0}, // 请求携带数据
dataType: ‘json’, // 接收的数据类型
isAsync: true // 是否异步请求
})
.then(data => {
console.log(请求成功,数据为${data}
)
})
.catch(err => {
console.log(请求失败,状态为${err}
)
})
其调用的是一个综合的方法,传入的参数是一个对象,对象中传入多个参数。这段代码是发送了一个 get
请求,地址为 example.php
,携带的参数有 query
值为 4
、em
值为 0
,所接收返回数据的类型为 json
,请求为异步请求
特别的是,该方法的回调函数是通过 promise
实现的,即该方法返回一个 promise
对象,在 then
函数中处理请求成功的情况,在 catch
函数中处理请求失败的情况
若没有了解过 promise
的小伙伴建议先花几分钟了解一下,因为这是异步编程最常用的一个语法,下面放上文章链接——[深入了解Promise对象,写出优雅的回调代码,告别回调地狱
]( )
接下来我们就针对上述给出的例子,逐个封装
因为 XMLHttpRequest
对象有一定的兼容性,因此我们在封装ajax方法之前可以先封装一个方法用来动态创建一个兼容性稍微好点的XHR对象(其中主要是兼容IE5和IE6)
我们都知道JQuery都是将方法封装在一个名为 $
的对象中的,我们也这么做
let $ = {
createXHR: function() {
// 若浏览器支持,则创建XMLHttpRequest对象
if(window.XMLHttpRequest) {
return new XMLHttpRequest()
}
// 若不支持,则创建ActiveXobject对象
else {
return new ActiveXObject()
}
}
}
首先查阅JQuery的 get
方法可知,其接收四个参数:URL、data、callback、dataType,分别表示请求的url地址、携带的参数、成功回调函数、返回数据的类型
let $ = {
// 动态生成XHR对象的方法
createXHR: function() {
if(window.XMLHttpRequest) {
return new XMLHttpRequest()
} else {
return new ActiveXObject()
}
},
get: function(url, data, callback, dataType) {
// 避免dataType大小写的问题
let dataType = dataType.toLowerCase()
// 如果有传入data,则在url后面跟上参数
if(data) {
url += ‘?’
Object.keys(data).forEach(key => url += ${key}=${data[key]}&
)
url = url.slice(0, -1)
}
// 调用我们封装的方法生成XHR对象
let xhr = this.createXHR()
// 创建get请求
xhr.open(‘get’, url)
// 发送请求
xhr.send()
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
// 若dataType为json,则将返回的数据通过JSON.parse格式化
let res = dataType === ‘json’ ? JSON.parse(xhr.responseText) : xhr.responseText
// 调用回调函数,并把参数传进去
callback(res, xhr.status, xhr)
}
}
}
},
}
分享
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
{
if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
// 若dataType为json,则将返回的数据通过JSON.parse格式化
let res = dataType === ‘json’ ? JSON.parse(xhr.responseText) : xhr.responseText
// 调用回调函数,并把参数传进去
callback(res, xhr.status, xhr)
}
}
}
},
}