原生 ajax 详解

做过前后端分离的同学,肯定都知道 ajax 这个异步通信方法


定义

首先肯定是要知道什么是 ajax,毕竟不能保证每个读这篇文章的人都是有前后端分离经验的人(

Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式、快速动态网页应用的网页开发技术,无需重新加载整个网页的情况下,能够更新部分网页的技术。

通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

说这么复杂,其实就是一种前端主动向后端发送 HTTP 请求的技术

原生写法

通过 JS 库 XMLHttpRequest 实现

一般写法如下

1
2
3
4
5
6
7
8
let xhr = new XMLHttpRequest()
xhr.open('GET','https://www.baidu.com/')
xhr.onreadystatechange = res => {
if(xhr.readystate === 4 && xhr.status === 200) {
console.log(res)
}
}
xhr.send()

接下来逐条解释

创建请求

通过 new XMLHttpRequest() 可以创建一个请求

设置请求方法和路径

通过 xhr.open 方法可以设置请求方法和请求路径

通常 open 方法一般接受两个参数

  1. method,表示 HTTP 动词,默认支持 ‘GET’ 或 ‘POST’,大小写没有影响,但一般是大写
  2. url,表示请求的地址,本例中请求百度首页

请求默认是异步的,但是当然还可以设置请求为同步,但是严重影响用户体验,故本文不介绍

请求状态

一般指 xhr.readystate 和 xhr.status

readystate

xhr 一般有 5 个 readystate,含义分别如下

readystate 含义
0 请求被创建
1 请求被 open
2 请求已经设置好回调,等待发送
3 请求已经被 send,等待响应
4 请求已经收到响应(不一定是成功)

因为 readystate === 4 不一定代表成功,所以还引入了第二个属性

status

表示请求返回的响应的 HTTP 状态码

一般 2 开头的表示成功,此处为简单起见直接取 200 来判断

设置回调

通过 readystatechange 事件来监听 readystate 的状态以回调

当 readystate 变为 4 时,会向回调函数中传入一个参数作为结果

如果成功,则是取回的值,如果失败,则多半没有内容,具体的可以查看 Chrome Network 中的 Response

所以,我们通过 xhr.onreadystatechange = 包含一个参数的函数,来获取响应的值,并在 readystate === 4 && status === 200 ——响应成功时,打印取回的值

注意,设置回调函数要先于发送请求,否则请求异常

发送请求

当必要的设置都完成后,就可以发送请求了

可以通过 xhr.send() 方法来发送请求

send 方法接受一个可选参数,表示附在请求 body 中的内容,一般是 POST 请求才使用,GET 请求请直接使用拼接 URL

其它功能

当然,还有 abort 方法取消请求、setRequestHeader 方法设置请求头等,此处不介绍了,详询 mdn

封装

初级封装就是把上文的代码封装成一个 ajax 方法

1
2
3
4
5
6
7
8
9
10
11
function ajax(method,url,callback,data){
let xhr = new XMLHttpRequest()
xhr.open(method,url)
xhr.onreadystatechange = res => {
if(xhr.readystate === 4 && xhr.status === 200) {
callback(res)
}
}
xhr.send(data)
}
ajax('GET','https://www.baidu.com/',console.log)

高级一点的就是用 Promise 封装

1
2
3
4
5
6
7
8
9
10
11
12
13
function ajax(method,url,data){
return new Promise((resolve,reject)=>{
let xhr = new XMLHttpRequest()
xhr.open(method,url)
xhr.onreadystatechange = res => {
if(xhr.readystate === 4 && xhr.status === 200) {
resolve(res)
}
}
xhr.send(data)
})
}
ajax('GET','https://www.baidu.com/').then(res => console.log(res))

再高级的我也不会了,就这样吧2333

axios

现在只有练习和面试的时候会手写原生 ajax 了,正式开发中都是使用基于 ajax 原理的库 axios

axios 的使用方法与上文中的 Promise 封装相似,详询 axios 中文网,或各个框架的本地化 axios 文档


感谢阅读

--It's the end.Thanks for your read.--