ch2. XHR的理解和使用
2.1 理解
- 使用XMLHttpRequest(XHR)对象可以与服务器交互,也就是发送ajax请求
- 前端可以获取到数据,而无需让整个的页面刷新
- 这使得Web页面可以只更新页面的局部,而不影响用户的操作
2.2 区别一般http请求与ajax请求
-
ajax请求是一种特别的http请求
-
对服务器来说,没有任何区别,区别在浏览器端
-
浏览器端发请求:只有XHR或fetch发出的才是ajax请求,其他所有的都是非ajax请求
-
浏览器端接收到响应
(1)一般请求:浏览器一般会直接显示响应体数据,也就是我们常说的刷新/跳转页面
(2)ajax请求:浏览器不会对界面进行任何更新操作,只是调用监视的回调函数并传入相关数据
2.3 API
-
XMLHTTPRequest(): 创建XHR对象的构造函数
-
status: 响应状态码值,比如200,400
-
statusText: 响应状态文本
-
readyState: 标识请求状态的只读属性
0:初始
1:open()之后
2:send()之后
3:请求中
4:请求完成
-
onreadystatechange: 绑定readyState改变的监听
-
responseType: 指定响应数据类型,如果是json,得到响应后自动解析响应体数据
-
response: 响应体数据,类型取决于responseType的指定
-
timeout: 指定请求超时。默认为0没有限制
-
ontimeout: 绑定超时的监听
-
onerror: 绑定请求网络错误的监听
-
open(): 初始化一个请求,参数为:{method, url, async}
-
send(data): 发送请求
-
abort(): 中断请求
-
getResponseHeader(name): 获取指定名称的响应头值
-
getAllResponseHeader(): 获取所有响应头组成的字符串
-
setResponseHeader(name, value): 设置请求头
2.4 XHR的ajax封装(简单版axios)
2.4.1 特点
-
函数的返回值为promise,成功的结果为response,异常的结果为error
-
能处理多种类型的请求:GET/POST/PUT/DELETE
-
函数的参数为一个配置对象
{
url: ’ ', //请求地址
method: ’ ', //请求方式为GET/POST/PUT/DELELTE
params: { }, //GET/DELETE请求的query参数
data: { }, //POST或DELETE请求的请求体参数
}
-
响应json数据自动解析为js
2.4.2 实例
function axios({
url,
method = 'GET',
params = {},
data = {}
}){
//返回一个promise对象
return new Promise((resolve, reject) => {
//处理method
method = method.toUpperCase()
//处理query参数(拼接到url) id=1&xxx='abc'
let queryString = ''
Object.keys(params).forEach(key => {
queryString += `${key}=${params[key]}&`
})
is(queryString){
//去掉最后的&
queryString = queryString.substring(0, queryString.length-1)
//拼接到url上
url += '?' + queryString
}
//1. 执行异步ajax请求
//1.1 创建xhr对象
const request = new XMLHttpRequest()
//1.2 打开连接(初始化请求,没有请求)
request.open(method, url, true)
//1.3 发送连接
if (mothod === 'GET' || method === 'DELETE') {
request.send()
}else if (method === 'POST' || method === 'PUT'){
//1.3.1 告诉服务器请求体的格式是json
request.setRequestHeader('Content-Type', 'application/json;charset=utf-8')
request.send(JSON.stringify(data)) //1.3.2 发送json格式请求体参数
}
//2. 绑定状态改变的监听
request.onreadystatechange = function(){
//2.1 如果请求没有完成,直接结束
if(request.readyState != 4){
return
}
//如果响应状态码在[200, 299],代表成功
const {status, statusText} = request
//2.2 如果请求成功了,调用resolve()
if(status >= 200 &status <= 299){
const response = {
data: JSON.parse(request.response)
status,
statusText
}
resolve(response)
}else { //2.2如果请求失败了,调用reject()
reject(new Error('request error status is' + status))
}
}
})
}
//1.GET请求:从服务器获取数据
function testGet(){
axios({
url: 'http://localhost:3000/posts',
method: 'GET',
params: {
id: 1,
xxx: 'abc'
}
}).then(
response => {
console.log(response)
},
error => {
alert(error.message)
}
)
}
//2.POST请求:服务器保存数据
function testPost(){
axios({
url: 'http://localhost:3000/posts',
method: 'POST',
data: {
"title": "json-server---",
"author": "typicode---"
}
}).then(
response => {
console.log(response)
},
error => {
alert(error.message)
}
)
}
//3.PUT请求:服务器更新数据
function testPut(){
axios({
url: 'http://localhost:3000/posts/1',
method: 'PUT',
data: {
"title": "json-server+++",
"author": "typicode+++"
}
}).then(
response => {
console.log(response)
},
error => {
alert(error.message)
}
)
}
//4.DELETE请求:服务器删除数据
function testDelete(){
axios({
url: 'http://localhost:3000/posts/2',
method: 'DELETE'
}).then(
response => {
console.log(response)
},
error => {
alert(error.message)
}
)
}