ajax:Asynchronous JavaScript And XML,翻译过来就是“异步的 Javascript 和 XML”。MDN中对ajax介绍:
异步 JavaScript 和 XML 或 Ajax 本身不是一种技术,而是一种将一些现有技术结合起来使用的方法,包括:HTML 或 XHTML、CSS、JavaScript、DOM、XML、XSLT、以及最重要的 XMLHttpRequest 对象。
所以 Ajax 是一个技术统称,是一个概念模型,它囊括了很多技术,并不特指某一技术。它的特点是:局部刷新页面,无需重载整个页面。
利用 XMLHttpRequest 模块实现 Ajax。总共可以分为五步:
let xmlHttp;
if(window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlHttp = new XMLHttpRequest()
}else{
// code for IE6, IE5
xmlHttp = new ActiveXObject('Microsoft.XMLHTTP')
}
通过open()方法设置请求方式(GET/POST)和请求地址(url)
/**
* 第一个参数:请求的类型;GET 还是 POST;
* 第二个参数:表示请求的文件的地址url;
* 第三个参数:设置请求方法是不是异步async,true为异步, false为同步。默认为true
*/
xmlHttp.open('GET/POST', url, true)
// 可使用 setRequestHeader() 来设置HTTP请求头
// xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// send() 方法接受一个可选的参数,其作为请求主体;如果请求方法是 GET 或者 HEAD,则应将请求主体设置为 null。
xmlHttp.send(body)
XMLHttpRequest.onreadystatechange 会在 XMLHttpRequest 的readyState 属性发生改变时触发 readystatechange 事件的时候被调用。
readyState:请求状态码,表示异步对象目前的状态,readyState的值从0到4。
值 | 状态 | 描述 |
---|---|---|
0 |
UNSENT |
代理被创建,但尚未调用 open() 方法。 |
1 |
OPENED |
open() 方法已经被调用(即服务器连接已建立)。 |
2 |
HEADERS_RECEIVED |
并且头部和状态已经可获得。 |
3 |
LOADING |
请求处理中,但没有全部完成; |
4 |
DONE |
请求已完成。 |
status:http状态码;http状态码表示成功的http状态码有:
// 304状态码(Not Modified):表示客户端发送的请求资源未被修改,服务器端无需返回资源内容,而是直接使用缓存的内容。优化网络带宽的使用,减少了不必要的数据传输,提高网络的访问速度。
xmlHttp.status >= 200 && xmlHttp.status < 300 || xmlHttp.status == 304
responseText:后台返回的字符串形式的响应数据;
responseXML:后台返回的XML形式的响应数据;
const ajax = (options) => {
// 1、创建XMLHttpRequest实例
let xmlHttp;
if(window.XMLHttpRequest){
xmlHttp = new XMLHttpRequest()
}else{
xmlHttp = new ActiveXObject('Microsoft.XMLHTTP')
}
// 处理请求参数
const objToString = (obj) => {
obj._t = new Date().getTime()
let temp = []
for(let key in obj){
// 需要将key和value转成非中文的形式,因为url不能有中文。
temp.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]))
}
return temp.join("&")
}
let params = objToString(options.data || {})
// 2、构建请求(设置请求方式和请求地址)
if(options.type.toLowerCase() === 'get'){
xmlHttp.open(options.type, `${options.url}?${params}`, true)
// 3、发送请求
xmlHttp.send()
}else if(options.type.toLowerCase() === 'json'){
xmlHttp.open('POST', options.url, true)
xmlHttp.setRequestHeader('Content-type', 'application/json')
xmlHttp.send(JSON.stringify(options.data || {}))
}else{
xmlHttp.open(options.type, options.url, true)
xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
xmlHttp.send(params)
}
// 4、监听状态变化
xmlHttp.onreadystatechange = () => {
if(xmlHttp.readyState == 4){
// 5、处理返回结果
if(xmlHttp.status >= 200 && xmlHttp.status < 300){
options.success(xmlHttp.responseText)
}else{
options.fail(xmlHttp.responseText)
}
}
}
// 设置超时时间
if (options.timeout) {
timer = setTimeout(function () {
xmlHttp.abort(); //中断请求
}, options.timeout);
}
}
ajax({
type: 'get',
url: 'http://localhost:8080/api/getUserList.do',
data: { a: 123 },
timeout: 1000,
success: data => {
console.log('success', data);
},
fail: err => {
console.log('error', err);
},
});
可以发现,ajax只是一种异步请求的方式,并不特指某一种具体的实现方式,但随着使用这种方式实现网络请求时内部又包含请求的情况,就会出现回调地狱,这也是XHR的诟病之一,因此,后来才催生了更加优雅的请求方式(fetch跟axios)。