1. 什么是ajax?
Asynchronous JavaScript And XML(异步javascript和XML)
Ajax 是一个技术统称,是一个概念模型,它囊括了很多技术,并不特指某一技术,它很重要的特性之一就是让页面实现局部刷新。
特点:局部刷新页面,无需重载整个页面。 最终要实现的样子
ajax({
type: "GET",
url: "http://129.0.0.1"8080",
data: {a: 1,b: 2},
timeout: 3000,
success: (res) => {
console.log("成功",res)
},
error: (err) => {
console.log("失败",err)
}
})
2. XMLHttpRequest
XMLHttpRequest是实现ajax的一种方式是浏览器提供的一个构造函数
2.1 浏览器差异
先判断浏览器是否有XMLHttpRequest
构造函数,ie5\6是ActiveXObject
构造函数
let xmlhttp
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest()
}else{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP)
}
2.2 需要用到的属性和方法
实例化出来的xmlhttp有很多的属性和方法
常用的有onreadystatechange
、readyState
、status
、responseText
、responseXML
- readyState: 请求状态码,表示当前异步实例对象的状态,从0-4 默认为0
- 0:表示请求未初始化,还没有调用open()
- 1: 服务器连接已建立但是还没有调用send()
- 2: 请求已接受,正在处理中,这个时候可以从响应中获取到内容头
- 3: 请求处理中,响应中有部分数据可用,但是没有全部完成
- 4: 请求已完成,数据全部解析完毕,可以获取到全部响应的数据
- onreadystatechange:
- 主要是用来监听readyState的状态变化,每当readyState状态变化时就会触发这个方法
- status: http状态码(200-300[不包括],304)
- responseText: 后台返回的字符串形式的响应数据
- responseXML: 后台返回的XML形式的响应数据
2.3 请求方式和请求地址
使用open方法设置。有三个参数:请求方法、请求URL、是否异步
xmlHttp.open("POST","/api/user",true)
ajax的意义就是发起异步请求,所以第三个参数一定是true
注意:
IE浏览器有一个缓存问题:在IE浏览器中如果通过ajax发送的get请求,那么IE浏览器认为,同一个URL只有一个结果,所以如果请求地址没有变化,它就会直接返回上一次的请求结果。
所以通常的解决方法就是,每次get请求的URL拼接一个时间戳new Date().getTime()
用来保证每次请求的URL不一样
xmlHttp.open("get","/api/xxx"+(new Date().getTime()),true)
2.4 发送请求
通过send
方法发送请求
xmlhttp.send()
如果是post请求要使用setRequestHeader()
来添加HTTP请求头
xmlHttp.open("POST","ajax_test.html",true);
xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlHttp.send("fname=Henry&lname=Ford");
2.5 监听readyState
的状态变化
xmlhttp.onreadystatechange = () => {
if(xmlhttp.readyState == 4){
//请求完成
if(xmlhttp.status >= 200 && xmlhttp.status < 300 | xmlHttp.status == 304){
//c接收到服务器返回的数据
}else{
// 请求失败、响应错误
}
}
}
注意:如果请求的URL中有中文需要通过encodeURIComponent()转码
2.6.完整代码
const ajax = (option) => {
let xmlhttp
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest()
}else{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP)
}
// 将传入的data(对象)转化为string
let objToString = (obj) => {
obj.t = new Date().getTime() // 这里主要是为get请求准备以处理IE浏览器的缓存问题
let res = []
for(let key in obj){
res.push(`${encideURIComponent(key)}=encodeURIComponent(obj[key])`)
}
return res.join("&")
}
// 设置请求方式和请求URL
let str = objToString(option.data)
if(option.type.toLowerCase() === 'get'){
xmlhttp.open('get', option.url+'?t='+option.data.t+str,true)
xmlhttp.send()
}else{
xmlhttp.open(option.type, option.url, true)
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
xml.send(str)
}
// 监听状态变化
xmlhttp.onreadystatechange = function() {
clearInterval(timer)
if(xmlhttp.readyState === 4){
//请求完成
if(xmlhttp.status >= 200 && xmlhttp.status < 300 | xmlHttp.status == 304){
//c接收到服务器返回的数据
option.success(xmlhttp.responseText)
}else{
// 请求失败、响应错误
option.error(xmlhttp.responseText)
}
}
}
if(option.timeout){
timer = setInterval(() => {
xmlhttp.abort()//中断请求
clearInterval(timer)
},option.timeout)
}
}
2.7.总结
- 实例化 XMLHttpRequest,判断浏览器支持的构造函数是谁
- 判断请求方法,并连接。如果是get就直接将data数据拼接到url上,并且添加一个时间戳以处理IE浏览器的缓存问题。其他的方法就设置一个请求头
send
中发送数据 - 通过onreadystatechange 监听请求状态。
- 再根据http状态码判断请求是否成功
- 根据timeout的时间设置请求中断(要注意清除定时器)
3. fetch
fetch 是在 ES6 出现的。它是 XMLHttpRequest的替代品。
但是用的好好的,为什么要提代它呢?
待更新。。。