所谓AJAX
就是异步JavaScript
和XML
,是一种无须加载整个网页就能实现更新部分网页的技术
那如何发送一个AJAX
请求
1. 创建一个异步对象
var xmlhttp;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else {// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
通过XMLHttpRequest
构造函数创建一个异步对象xmlhttp
, IE6, IE5 使用ActiveXObject
创建,创建的这个异步对象上有很多属性和方法,常用的有:
(1)onreadystatechange
监听异步对象请求状态码readyState
的改变,每当readyState
改变时,就会触发onreadystatechange
事件
(2)readyState
:请求状态码
readyState
表示异步对象目前的状态,状态码从0到4:
0
: 表示请求未初始化,还没有调用open()
1
: 服务器连接已建立,但是还没有调用 send()
2
: 请求已接收,正在处理中(通常现在可以从响应中获取内容头)
3
: 请求处理中,通常响应中已有部分数据可用了,没有全部完成
4
: 当readyState状态码为4时,表示请求已完成;此阶段确认全部数据都已经解析完毕,可以通过异步对象的属性获取对应数据
(3)status
:http状态码
http状态码表示成功的http状态码有xmlhttp.status >= 200 && xmlhttp.status < 300 || xmlhttp.status == 304
(4)responseText
:后台返回的字符串形式的响应数据
(5)responseXML
:后台返回的XML
形式的响应数据
2. 设置请求方式和请求地址
创建异步对象之后,通过open()
方法设置ajax
请求方式和请求地址
格式:xmlhttp.open("GET/POST","ajax-get.txt",true);
第一个参数:请求的类型;GET
还是POST
第二个参数:表示请求的文件的地址url
第三个参数:设置请求方法是不是异步async
,true
为异步, false
为同步。AJAX
存在的意义就是发异步请求,所以第三个参数永远传true
这里有个问题,就是IE
中的缓存问题
在IE
浏览器中,如果通过Ajax
发送GET
请求,那么IE
浏览器认为,同一个URL只有一个结果,如果地址没有发生变化,它就会把上一次返回的结果,直接返回
。这样我们不能实时的拿到变化后的数据。如果要想我们拿到实时数据,必须保证每次的URL都是不一样的,有两种方式:
(1)Math.random()
;随机数
(2)new Date().getTime()
;1970.01.01至当前的毫秒数。
即在请求地址后面拼接上?t=随机数或者1970.01.01至当前的毫秒数
所以在IE
中通过ajax
发送get
请求时,可以设置请求地址为:
xmlhttp.open("GET","ajax-get.txt?t=" + (new Date().getTime()),true);
//或
xmlhttp.open("GET","ajax-get.txt?t=" + Math.random(),true);
3. 发送请求
直接通过异步对象的send()发送请求
xmlhttp.send();
特别注意的是: 如果发送POST
请求,请使用setRequestHeader()
来添加HTTP
请求头,并在send()
方法中传递要发送的数据:
xmlhttp.open("POST","ajax_test.html",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Henry&lname=Ford");
4. 通过onreadystatechange监听状态变化
每当异步对象的readyState
发生改变,就会触发onreadystatechange
函数,当readyState
变成为4
时,表示当前状态是请求完毕的状态,同时当http
的响应码status
为200
到300
之间(包括200
和300
)或为304
时,表示ajax
请求成功;当http状态码不是200
到300
之间的数也不是304
时,表示请求不成功
//4.监听状态变化
xmlhttp.onreadystatechange = function(){
// 判断当前状态改变是请求完毕的状态吗
if (xmlhttp.readyState === 4) {
if (xmlhttp.status >= 200 && xmlhttp.status < 300 || xmlhttp.status == 304) {
console.log("成功的接收到服务器返回的数据");
}else{
console.log("不成功!");
}
}
}
5. 处理返回的结果
如果成功,可通过异步对象的responseText
属性来获取服务器返回的字符串
console.log(xmlhttp.responseText);
根据上述情况,如果每次请求都要手写以上五个步骤,那很麻烦,接下来,我们来封装一个方法ajax()
用于发送请求
封装的时候,需要注意
(1)URL
当中只能出现字母 数字 下划线和ASCII
码,不能出现中文,可以使用encodeURIComponent()
转码
(2)当我们利用我们的ajax放的发送一个请求到远处服务器时,我们需要等待远程服务器去响应我们的请求,等待远程服务器将响应的结果返回给我们,但是这个响应的速度是不确定的,因为响应的速度是由本地网络和远程服务器的网速等共同决定的,所以我们不可能一直等待服务器的响应。那么这里我们需要新增另外一个功能:设置超时时间的功能,即告诉它我的请求会等待多长的时间,如果这么长的时间内都没有响应我们发送的请求,那我就在这里自动的终止这次请求;
function ajax(type, url, obj, timeout, success, error) {
// 0.将对象转换成字符串
var str = objToString(obj);
// 1.创建一个异步对象xmlhttp;
var xmlhttp, timer;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// 2.设置请求方式和请求地址;
// 判断请求的类型是POST还是GET
if (type === 'GET') {
xmlhttp.open(type, url + "?t=" + str, true);
// 3.发送请求;
xmlhttp.send();
} else {
//如果是post请求,需要设置请求头
xmlhttp.open(type, url, true);
// 注意:在post请求中,必须在open和send之间添加HTTP请求头:setRequestHeader(header,value);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// 3.发送请求;
xmlhttp.send(str);
}
// 4.监听状态的变化;
xmlhttp.onreadystatechange = function () {
clearInterval(timer);
if (xmlhttp.readyState === 4) {
if (xmlhttp.status >= 200 && xmlhttp.status < 300 || xmlhttp.status == 304) {
// 5.处理返回的结果;
success(xmlhttp);//成功后回调;
} else {
error(xmlhttp);//失败后回调;
}
}
}
//处理obj
function objToString(obj) {
obj.t = new Date().getTime();
var res = [];
for (var key in obj) {
//需要将key和value转成非中文的形式,因为url不能有中文。使用encodeURIComponent();
res.push(encodeURIComponent(key) + " = " + encodeURIComponent(obj[key]));
}
return res.join("&");
}
//判断外界是否传入了超时时间
if (timeout) {
timer = setInterval(function () {
xmlhttp.abort();//中断请求
clearInterval(timer);
}, timeout);
}
}
在使用自己封装的代码的时候,感觉跟jQuery
官方的ajax
还是有一定的差异,所以还需要进一步完善
首先看第一个问题,传递多个参数,需要保持传递顺序。解决方案是可以改写成传递的是一个对象;因为对象里面的值,传递的是一个对象就不用考虑先后顺序,里面用的参数通过对象名.属性名
的形式获取
第二,传递请求类型的区分大小写,jQuery
官方的是大小写都可以;解决方案是可以使用toLowerCase()
或者toUpperCase()
将类型转成大写或小写再对比;
第三,我们传递的数据用的名字是obj
,jQuery
官方用的是data
,语义更适合。所以将传递数据obj
改成data
完善如下:
function ajax(option) {//type,url,obj,timeout,success,error将所有参数换成一个对象{}
// 0.将对象转换成字符串
var str = objToString(option.data);
// 1.创建一个异步对象xmlhttp;
var xmlhttp, timer;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// 2.设置请求方式和请求地址;
// 判断请求的类型是POST还是GET
if (option.type.toLowerCase() === 'get') {
xmlhttp.open(option.type, option.url + "?t=" + str, true);
// 3.发送请求;
xmlhttp.send();
} else {
xmlhttp.open(option.type, option.url, true);
// 注意:在post请求中,必须在open和send之间添加HTTP请求头:setRequestHeader(header,value);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// 3.发送请求;
xmlhttp.send(str);
}
// 4.监听状态的变化;
xmlhttp.onreadystatechange = function () {
clearInterval(timer);
if (xmlhttp.readyState === 4) {
if (xmlhttp.status >= 200 && xmlhttp.status < 300 || xmlhttp.status == 304) {
// 5.处理返回的结果;
option.success(xmlhttp);//成功后回调;
} else {
option.error(xmlhttp);//失败后回调;
}
}
}
//处理obj
function objToString(data) {
data.t = new Date().getTime();
var res = [];
for (var key in data) {
//需要将key和value转成非中文的形式,因为url不能有中文。使用encodeURIComponent();
res.push(encodeURIComponent(key) + " = " + encodeURIComponent(data[key]));
}
return res.join("&");
}
//判断外界是否传入了超时时间
if (option.timeout) {
timer = setInterval(function () {
xmlhttp.abort();//中断请求
clearInterval(timer);
}, timeout);
}
}
最后传参形式变成
ajax({
type: xxx,
url: xxx,
data: xxx,
timeout:xxx,
success: xxx,
error:xxx
});
以上就是ajax相关的内容,基本功能是能实现,但跟jQuery的ajax还是差很多,考虑的也不全,想了解jQuery的ajax可以阅读以其源码,后面有时间我也会一起来看一下
网友评论