AJAX即异步的JavaScript 和 XML(Asynchronous JavaScript And XML)
在网页中利用XMLHttpRequest对象和服务器进行数据交互的方式,就是AJAX
AJAX本身不是一种新技术,而是将现有技术结合起来的方法
具体来说,实现AJAX有两种方式
第一种则是通过XHR
XHR即XMLHTTPRequest,这是一个用于网络请求的对象,我们可以用它来发送和接收JSON,XML,HTML和TEXT等类型的数据
创建一个AJAX请求通常分为四步
XMLHTTPRequestconst XHR = new XMLHttpRequest()
onreadystatechange事件,这个事件将会在网络请求状态每次改变后执行XHR.onreadystatechange = function() {
console.log("状态发生了改变");
}
open方法配置网络请求XHR.open("get","")
open方法接收三个参数,第一个参数是请求类型,如get、post、delete等等,第二个参数为向其发送请求的URL,第三个参数为布尔类型的可选参数,表示是否为异步操作,默认为trueXHR.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返回值是一个PromiseFetch不像XHR一样所有操作都在一个对象上XHR在上传文件时可以监控进度,Fetch不行Fetch将数据的响应分成了两个阶段
当服务器返回了数据时为第一个阶段
检查http响应头来判断请求是否成功url不正确等导致Fetch无法建立http请求,那么Promise就会rejecthttp响应码为404,500等异常状态码时将不会导致errorresponse.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
}