重走Ajax之路2


重走Ajax之路(二)

前一篇已经简单介绍了下Ajax的用法了(只是简单的GET请求),下面就来捣鼓下Ajax的其他内容

后端可以使用上一篇最后的express

同步请求

调用open方法时,第三个参数是false时,就是同步请求,这时候,JavaScript会堵塞,当服务器响应之后才继续执行。

这时候,绑定的readystatechange事件不会有反应,因为同步请求的话,JavaScript会堵塞,当服务器响应之后才继续执行,所以当我们绑定事件时,已经接收到响应了,所以状态不会再变也就不会触发readystatechange事件。

这时候可以直接把readystatechange事件的逻辑外移,不再需要绑定事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
function fetchData() {
const xhr = new XMLHttpRequest()

xhr.open('get', 'http://localhost:8088', false)

xhr.send(null)

if (xhr.readyState === 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log(xhr.responseText)
}
}
}

也可以把绑定readystatechange事件的步骤提前到调用open方法之前,这样子,当服务器响应之后,状态会从0变成4,就会触发事件。

设置请求头

有时候,我们发送请求时,还需要设置请求头,比如请求头需要携带token。这时候就需要在open()之后,send()之前调用setRequestHeader设置请求头。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function fetchData() {
const xhr = new XMLHttpRequest()

xhr.open('get', 'http://localhost:8088')

// 设置请求头
xhr.setRequestHeader('token', '123456')

xhr.send(null)

xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log(xhr.responseText)
}
}
}
}

获取响应头

和设置请求头类似,我们有时候从服务器响应中获取响应头,比如把token放到了响应头里。

我们可以通过getAllResponseHeaders方法得到能访问的所有响应头,也可以通过getResponseHeader('myheader')来获取特定的响应头。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// 获取全部响应头
const allHeaders = xhr.getAllResponseHeaders()
console.log(allHeaders)

// 获取特定响应头
const token = xhr.getResponseHeader('token')
console.error(token)

}
}
}

POST请求发送数据(json格式)

GET请求就是通过给GET请求URL后面添加查询字符串参数,如/getName?user=clz&age=21

这个只需要使用字符串拼接即可。

POST请求稍微复杂一点点。
先改造一下提供接口的express先。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const express = require('express')
const cors = require('cors')

const app = express()

app.use(cors())

// 解析请求体的中间件(json格式)
app.use(express.json())

app.post('/login', function (req, res) {
console.log(req.body)

res.status(200).json({
data: {
...req.body,
tt: 'ttt'
},
msg: '登录'
})
})

app.listen(8088, () => {
console.error('http://localhost:8088')
})

我们可以通过send方法,接收一个参数,作为请求体发送出去。
那么能不能直接把一个对象作为请求体发送出去呢?
试一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function fetchData() {
const xhr = new XMLHttpRequest()

xhr.open('post', 'http://localhost:8088/login')

xhr.send({
name: 'clz',
age: 21
})

xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log(xhr.responseText)

}
}
}
}

答案是不行的。如果我们直接将对象发过去,会自动调用toString方法变成字符串形式。

那么,我们在换成JSON字符串再试试。

1
2
3
4
xhr.send(JSON.stringify({
name: 'clz',
age: 21
}))

这时候,我们的数据已经正常的发出去了,但是,后端那边并没有介绍到,打印的req.body是空的。
这是因为浏览器发送请求是由严格规范的,我们的请求体是JSON字符串格式,还得设置内容类型Content-Typejson

1
2
3
4
5
xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8')
xhr.send(JSON.stringify({
name: 'clz',
age: 21
}))


后端正常收到请求体

超时

我们可以给XHR对象增加timeout属性,表示发送请求后等待多少毫秒,如果在这段时间内响应不成功就中断请求,并且会触发timeout事件。(可以在express增加一个定时器响应,时间设置长一点,来模拟请求超时)

1
2
3
4
5
6
// 设置2s超时
xhr.timeout = 2000

xhr.ontimeout = function () {
alert('响应超时,要中断请求啦')
}

ajax

取消未响应的请求

上面我们可以设置超时取消请求,当然也可以手动取消请求。
在没收到响应之前,调用abort方法可以取消请求。

1
2
3
4
5
6
const xhr = new XMLHttpRequest()

const cancelBtn = document.getElementById('cancel-btn')
cancelBtn.addEventListener('click', () => {
xhr.abort()
})

ajax


文章作者: 赤蓝紫
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 赤蓝紫 !
评论
  目录