xhr.readyState
0:请求未初始化(还没有调用 open())。
1:请求已经建立,但是还没有发送(还没有调用 send())。
2:请求已发送,正在处理中(通常现在可以从响应中获取内容头)。
3:请求在处理中;通常响应中已有部分数据可用了,但是服务器还没有完成响应的生成。
4:响应已完成;您可以获取并使用服务器的响应了。
原理
<script>
window.onload=function (ev) {
var btn=document.querySelector('button');
btn.onclick=function () {
//1.创建一个异步对象
var xmlhttp=new XMLHttpRequest();
//2.设置请求方式和请求地址
/*
open('method','url',async);
method:请求的类型:GET或POST
url:文件在服务器上的位置
async:true(异步)或false(同步)
*/
xmlhttp.open('get','4-ajax-get.php',true);
//3.发送请求
xmlhttp.send();
//4.监听状态变化
xmlhttp.onreadystatechange=function (ev2) {
/*
0:请求初始化
1:服务器连接已建立
2:请求已接收
3:请求处理中
4:请求已完成,且响应已就绪
*/
if (xmlhttp.readyState===4){//判断是否到4
if(xmlhttp.status>=200&&xmlhttp.status<300||xmlhttp.status===304){
//5.处理返回结果
console.log('接受到服务器返回的结果');
//6.访问服务器
console.log(xmlhttp.responseText);
}else {
console.log('没有接受到服务器返回的结果');
}
}
}
}
}
</script>
简易封装
function ajax(methon, url, callback) {
let oReq = new XMLHttpRequest();
oReq.onreadystatechange = function () {
if (oReq.readyState === 4 && oReq.status === 200) {
callback(oReq.responseText);
}
};
oReq.open(methon, url, true);
oReq.send();
}
ajax('get', 'data.json', function (data) {
console.log(data);
});
Promise 简易封装
function ajax (method, url, data, callback) {
return new Promise((resolve, reject) => {
let req = new XMLHttpRequest()
req.open(method.toUpperCase(), url)
req.withCredentials = true // 允许跨域
req.onreadystatechange = handler
req.responseType = 'json'// 规定响应数据格式为 json
req.setRequestHeader('Content-type', 'multipart/form-data')
req.send(data)// FormData
function handler () {
if (req.readyState !== 4) return
if (req.status === 200) {
callback && callback(req.responseText)
resolve(req.responseText)
} else {
reject(new Error(this.statusText))
}
}
})
}
let form = new FormData()
form.append('name', this.form.account)
form.append('password', this.form.password)
ajax('post', './ajax.json', form, req => {
console.log(req)
})
ajax('get', './ajax.json', form)
.then(req => {
console.log(req)
return ajax('post', './ajax.json')
})
.then(req => {
console.log(req)
})
.catch(err => {
console.log('err:' + err)
})
Class 封装
class Ajax {
constructor(url, headers) {
this.url = url
this.headers = headers
}
get(url, data) {
let xhr = new XMLHttpRequest()
xhr.open('GET', this.url + url + sentData(data))
if (this.headers) {
for (let i in this.headers) {
xhr.setRequestHeader(i, this.headers[i])
}
}
xhr.send()
function sentData(data) {
let str = '?'
for (let i in data) {
str += `${i}=${data[i]}&`
}
return str.slice(0, str.length - 2)
}
}
post(url, data) {
let xhr = new XMLHttpRequest()
xhr.open('POST', this.url + url)
if (this.headers) {
for (let i in this.headers) {
xhr.setRequestHeader(i, this.headers[i])
}
}
xhr.send(JSON.stringify(data))
}
}
// let $ = new Ajax('https://www.baidu.com', { 'Content-Type': 'application/x-www-form-urlencoded' })
let $ = new Ajax('https://www.baidu.com', { 'Content-Type': 'text/plain' })
$.get('/foo', { name: 'bob', age: 18 })
$.post('/bar', { name: 'lucy', age: 16 })
全面封装并兼容IE
function obj2str(data) {
data.t = new Date().getTime();
var res = [];
for (var key in data) {
//中文转换(在URL中不能出现中文)
res.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
}
return res.join('&');
}
function Ajax(option) {
//将对象转为字符串
var str = obj2str(option.data);
var xml;
var timer;
//兼容ie 1、创建一个异步对象
if (window.XMLHttpRequest) {
xml = new XMLHttpRequest();
} else {//IE5和6
xml = new ActiveXObject('Microsoft.XMLHTTP');
}
//判断请求类型 2、设置请求方式和请求地址 3、发送请求
if (option.type.toLowerCase() === 'GET') {
xml.open(option.type, option.url + '?' + str, true);
xml.send();
} else {
xml.open(option.type, option.url, true);
//post请求注意点:此代码位置固定
xml.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xml.send(str);
}
//IE缓存 4、监听状态变化
xml.onreadystatechange = function () {
//判断服务器处理
if (xml.readyState === 4) {
clearInterval(timer);
if (xml.status >= 200 && xml.status < 300 || xml.status === 304) {
// console.log('请求成功');
//访问服务器
// console.log(xml.responseText);
option.success(xml);
} else {
// console.log('请求失败');
option.error(xml.status);
}
}
};
//判断是否超时
if (option.timeout) {
timer = setInterval(function () {
alert('网络请求超时');
xml.abort();
clearInterval(timer);
}, option.timeout);
}
}
//应用
window.onload = function () {
var btn = document.getElementById('btn');
btn.onclick = function () {
Ajax({
url: '7-ajax-post.php',
type: 'Post',
data: {
'name': '胡歌',
'age': 19
}
,
timeout: 3000,
success: function (xml) {
console.log(xml.responseText);
},
error: function (xml) {
console.log('error');
}
})
}
}