AJAX
即异步
的JavaScript 和 XML
(Asynchronous JavaScript And XML
)
在网页中利用XMLHttpRequest
对象和服务器进行数据交互
的方式,就是AJAX
AJAX
本身不是一种新技术,而是将现有技术结合起来的方法
具体来说,实现AJAX
有两种方式
第一种则是通过XHR
XHR
即XMLHTTPRequest
,这是一个用于网络请求
的对象,我们可以用它来发送和接收JSON
,XML
,HTML
和TEXT
等类型的数据
创建一个AJAX
请求通常分为四步
XMLHTTPRequest
const XHR = new XMLHttpRequest()
onreadystatechange
事件,这个事件将会在网络请求状态每次改变
后执行XHR.onreadystatechange = function() {
console.log("状态发生了改变");
}
open
方法配置网络请求XHR.open("get","")
open
方法接收三个
参数,第一个参数是请求类型
,如get
、post
、delete
等等,第二个参数为向其发送请求的URL
,第三个参数为布尔类型的可选参数
,表示是否为异步操作
,默认为true
XHR.send()
通过GET
请求来传递数据只能通过query
参数
XHR.open("get","http://localhost:8088/get?name=zhangsan&age=18")
XHR.send()
事实上GET
请求并不适合传递数据,如果想要大量传递数据需要使用POST请求
POST
请求通过表单
传递数据const form = document.querySelector("form")
const formData = new FormData(form)
XHR.open("post","http://localhost:8088/post")
XHR.send(formData)
请求头
为application/x-www-form-urlencoded
的方式XHR.open("post","http://localhost:8088/post")
const data = "name=zhangsan&age=18"
XHR.setRequestHeader("Content-type","application/x-www-form-urlencoded")
XHR.send(data)
请求头
为application/json
的方式XHR.open("post","http://localhost:8088/post")
const data = JSON.stringify({name:"zhangsan",age:18})
XHR.setRequestHeader("Content-type","application/json; charset=utf-8")
XHR.send(data)
在一次网络请求中XHR
的状态会发生很多次变化
我们可以在onreadystatechange
事件中通过XHR.readyState
拿到每次状态变化的值
状态码 | 意义 |
---|---|
0 | 请求被创建,但未调用open方法 |
1 | open方法被调用 |
2 | send方法被调用,并且头部和状态已可取得 |
3 | 下载中 |
4 | 下载操作已完成 |
事件名 | 作用 |
---|---|
loadstart | 请求开始 |
progress | 第一个响应数据包到达 |
abort | 调用了XHR.abort()取消了请求 |
error | 发生连接错误 |
load | 请求完成 |
timeout | 请求超时,前提是设置了timeout |
loadend | 在load、error、timeout、abort之后触发 |
发送了请求过后我们可以通过response
属性来获取返回的数据
const res = XHR.response
返回数据的类型则是由responseType
来决定
XHR.responseType = "json"
如果responseType
值为空则为默认值text
responseText
返回的是text
数据
responseXML
返回的则是XML
在早期的服务器中返回的数据多是text
和XML
,所以那时多用responseText
和responseXML
来获取结果
现在服务器返回多为json
数据
除了请求有状态码
之外,响应也有对应的状态码
我们可以通过status
和statusText
来获取
const status = XHR.response.status;
const statusText = XHR.response.statusText;
具体关于HTTP响应码
相关的内容可以看我这篇文章
前端网络基础
为了避免过长的网络请求时间
而服务器迟迟无法返回数据
的情况,我们可以设置一个超时时间
当达到设置的时间后如果还没能拿到数据则会自动取消这个请求
默认值为0
,表示没有设置超时时间
timeout
的单位为毫秒
XHR.timeout = 10*1000
function AJAX({
method,
url,
asy = true,
timeout = 0,
data = {},
success,
failure
}) {
const xhr = new XMLHttpRequest();
xhr.responseType = "json"
xhr.timeout = timeout
xhr.onload = function () {
if (xhr.status == 200) {
success(xhr.response)
} else {
failure(xhr.status, xhr.statusText)
}
}
if (method || url || success || failure) {
throw new Error("未传入指定参数")
return;
} else if (method.toLowerCase() == "get") {
let query = []
for (const key in data) {
query.push(`${key}=${data[key]}`)
}
url = url + "?" + query.join("&")
xhr.open(method, url, asy)
xhr.send()
} else if (method.toLowerCase() == "post") {
xhr.open(method, url, asy)
xhr.setRequestHeader("Content-type", "application/json")
xhr.send(JSON.stringify(data))
} else {
throw new Error("不支持这种方法")
}
return xhr;
}
const xhr = AJAX({
method: "get",
url: "http://localhost:8088/get",
data: {
name: "zhangsan"
},
success: function (res) {
console.log(res)
},
failure: function (status, statusText) {
console.log(status, statusText)
}
})
Axios
是一个基于promise
的网络请求库
它不仅可以在浏览器
里发送网络请求,还可以在node.js
中发送请求
它还支持Promise
请求/响应拦截器
等等
当我们从Axios
中导入对象时使用的实例为默认实例
有时候默认实例
的配置并不是我们所需的
所以我们可以创建一个新的实例
并传入属于该实例的配置
const ajax = axios.create({
baseURL:"http://localhost:8088"
})
通过我们创建的这个实例
来发送请求
ajax.get("/get",{
params:{
}
}).then(res=>{
console.log(res)
})
ajax.post("/post",{
name:"zhangsan",
age:19
}
}).then(res=>{
console.log(res)
})
Axios也可以设置拦截器,拦截每次请求和响应
请求
拦截
axios.interceptors.request.use(function (config) {
console.log("请求成功拦截")
return config;
}, function (error) {
console.log("请求失败拦截")
return error;
});
响应
拦截
axios.interceptors.response.use(function (response) {
console.log("响应成功拦截")
return response;
}, function (error) {
console.log("响应失败拦截")
return error;
});
Fetch
是一种更加现代的网络请求方案
它是早期XMLHTTPRequest的替代方案
同样也是AJAX的另一种实现方式
和XHR
不同的是
Fetch
返回值是一个Promise
Fetch
不像XHR
一样所有操作都在一个对象上
XHR
在上传文件时可以监控进度,Fetch
不行Fetch
将数据的响应分成了两个阶段
当服务器返回了数据
时为第一个阶段
检查http响应头
来判断请求是否成功
url
不正确等导致Fetch
无法建立http
请求,那么Promise
就会reject
http响应码
为404
,500
等异常状态码
时将不会导致error
response.status
来获得http状态码
第二个阶段为我们通过其他方法获取数据
response.text()
文本
的形式返回response.json()
json
的形式返回发送get
请求
async function getData() {
const response = await fetch("http://localhost:8088/get")
const data = await response.json()
console.log(data)
}
发送post
请求
const params = {
name:"zhangsan",
age:18
}
async function getData() {
const response = await fetch("http://localhost:8088/get",{
method:"post",
headers:{
"Content-type", "application/json; charset=utf-8"
},
body:JSON.stringify(params)
})
const data = await response.json()
console.log(data)
}
我们可以基于Axios
简易封装一个自己的网络请求库
async function httpGet(url, params) {
const request = await axios.get(url, {
params
})
return request
}
async function httpPost(url, data) {
const request = await axios.post(url, data)
return request
}
axios.interceptors.request.use(function(config) {
return config;
}, function(error) {
return Promise.reject(error);
});
axios.interceptors.response.use(function(response) {
return response;
}, function(error) {
return Promise.reject(error);
});
export {
httpGet,
httpPost
}