AJAX原理—XMLHttpRequest

XMLHttpRequest(XHR)对象用于与服务器交互,axios实际上就是对XHR的封装

使用XMLHttpRequest

  1. 创建XHR对象
  2. 配置请求方法与URL
  3. 监听loadend加载完毕事件,接收响应结果
  4. 发送请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const xhr = new XMLHttpRequest();

xhr.open('POST', 'http://localhost:3000/');

xhr.setRequestHeader('Content-Type', 'application/json'); // 设置请求头,指示消息体类型为JSON

xhr.addEventListener('loadend', () => {
console.log(xhr.response);
})
// 若类型为GET则send后不能接数据
xhr.send(JSON.stringify({
name: 'abc',
age: 18,
}));

查询参数

格式为http://xxx.com?参数1=值1&参数2=值2

1
xhr.open("GET", 'http://localhost:3000?name=abc&age=18')

服务端(node.js的express)收到后可通过req.query取出

请求参数

也叫body参数,可通过post请求发送,发送请求时最好设置请求头声明携带的数据类型,如Content-Type: application/json

Promise

​ Promise表示管理一个异步操作最终状态和结果值的对象

使用

.then表示执行成功的回调函数,.catch表示执行失败的回调函数

1
2
3
4
5
6
7
8
9
10
const p = new Promise((resolve, reject) => {
// 执行操作
// resolve(值)表示成功,执行下一个then
// reject(值)表示失败,执行catch
})
p.then(response => {
console.log(response);
}).catch(error => {
console.log(error);
})

三种状态

  • pending待定,在promise管理的异步任务执行完毕之前的状态
  • fulfilled已兑现,执行完resolve()后的状态,将resolve的参数传递给then并执行回调函数
  • rejected已拒绝,执行完reject()后的状态,将reject的参数传递给catch并执行回调函数

Promise的状态只能改变一次,一旦被兑现/拒绝就无法改变

封装简易axios

初步实现

axios的.then和.catch来自Promise,因此只需在函数里return一个Promise即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function myAxios(config){
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open(config.method || 'GET',config.url)
xhr.addEventListener('loadend', ()=>{
if(xhr.status >= 200 && xhr.status <300){
try{
resolve(JSON.parse(xhr.response))
}
catch{
resolve(xhr.response)
}
} else{
reject(new Error(xhr.response))
}
})
xhr.send()
})
}
  • 不传入请求方法则默认为GET,使用逻辑中断||实现
  • 通过响应状态码判断请求是否发送成功,进而确定Promise的状态,并将response传过去
  • 失败时一般创建Error对象来存入错误信息
  • 使用try-catch来判断服务端传输来的数据是否是JSON,是则解析为对象,便于前端使用

使用方法有局限性,无法传入查询字符串

实现传入查询字符串

open前进行判断,因为查询字符串需要拼接在地址中

1
2
3
4
5
6
7
8
9
10
11
function myAxios(config){
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
if(config.params){
const queryString = new URLSearchParams(config.params).toString()
config.url += `?${queryString}`
}
xhr.open(config.method || 'GET',config.url)
...
})
}
  • URLSearchParams是浏览器提供的构造函数,传入对象可将其转化为查询字符串的格式,再使用toString将其转换成字符串的形式,最后将其与url拼接起来

实现携带请求体数据

1
2
3
xhr.setRequestHeader("Content-type", "application/json")
const data = config.data ? JSON.stringify(config.data) : undefined
xhr.send(data)
  • 在发送请求前设置请求头
  • 使用逻辑中断||获取data数据
  • 若用const data = JSON.stringify(config.data) || undefined,当data不存在时会报错

使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
myAxios({
url: 'http://localhost:8000/',
method: 'POST',
params:{
name: 'abc'
},
data: {
age: 18
}
}).then(result => {
console.log(result)
}).catch(error => {
console.log(error)
})