学习Ajax

1.XHR对象

        IE7+、Firefox、Opera、Chrome和Safari都支持原生XMLHttpRequest对象,IE6不支持,只支持ActiveXObject对象,该对象在IE11中已经不再支持了。

IE中有三种不同版本的XHR对象MSXML2.XMLHTTP、MSXML2.XMLHTTP.3.0、MSXML2.XMLHTTP.6.0,所以可以通过一下函数创建一个兼容所有浏览器的XHR:

 1 function createXHR() {
 2     if(typeof XMLHttpRequest != "undefined"){
 3         return new XMLHttpRequest();
 4     }else if(typeof ActiveXObject != "undefined"){
 5         if(typeof arguments.callee.activeXString != "string"){
 6             var versions = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"],i,len;
 7             for(i=0,len=versions.length; i<len; i++){
 8                 try {
 9                     new ActiveXObject(versions[i]);
10                     arguments.callee.activeXString = versions[i];
11                     break;
12                 }catch (ex){
13                     //跳过
14                 }
15             }
16         }
17         return new ActiveXObject(arguments.callee.activeXString);
18     }else {
19         throw new Error("No XHR object available.");
20     }
21 }

或者简洁一点的:

1 if(typeof window.XMLHttpRequest != 'undefined'){
2      var xhr = new XMLHttpRequest();
3 }else if(typeof window.ActiveXObject != 'undefined'){
4       var xhr = new ActiveXObject('Microsoft.XMLHTTP');
5}

也可以达到兼容ie的效果。

2.XHR用法

        创建完XHR对象后可通过open方法启用一个请求,传入三个参数请求方法、url、是否异步(默认true)。调用完open方法后,请求并没有被发送,需要通过send()方法发送,发送时可附带一些请求数据,无需附带数据时传入null。通过readystatechange事件监听请求状态和http状态。通过responseText获取响应信息,或者通过responseType来设置响应信息的类型直接通过response属性获得响应数据来进行处理。

        请求方式有两种GET、POST,get方式用于向服务器请求一些数据:

var btn = document.getElementById('btn');
        btn.onclick = function () {
            if(window.XMLHttpRequest != 'undefined'){
                var xhr = new XMLHttpRequest();
            }else if(window.ActiveXObject != 'undefined'){
                var xhr = new ActiveXObject('Microsoft.XMLHTTP');
            }
            xhr.onreadystatechange = function() {
                if(xhr.readyState == 4 && xhr.status == 200){
                    alert(xhr.responseText);
                }
            }

            xhr.open("GET",'data.txt',true); //获取data.txt
            xhr.send(null);
        }

readyState为请求的状态码,每次状态变化都会触发readystatechange事件,通过监听该事件来判断是否成功收到响应。

0:未初始化

1:启用,调用了open方法

2:发送数据,调用了send

3:接收数据,但未完全接收

4:数据接收完毕,可以使用

当状态码为4的时候,服务器响应就完成了,但此时只是完成了响应,数据是否可用还要通过http的状态吗status来判断:

1xx:信息,服务器收到请求

2xx:成功,操作被成功接收并处理

3xx:重定向,需要进一步操做以完成请求

4xx:客户端错误,(404)请求资源地址不正确

5xx:服务器错误

当状态码为200是,则成功收到响应数据,所以只需判断status==200&&readyState==4就可以了。

get方式也可以发送少量数据,将数据附在url上传给服务器:

var btn = document.getElementById('btn');
        btn.onclick = function () {
            var text = encodeURIComponent(document.getElementById('active').value); //用encodeURIComponent对字符串进行编码,会将多余的空格等进行转码
            if(window.XMLHttpRequest != 'undefined'){
                var xhr = new XMLHttpRequest();
            }else if(window.ActiveXObject != 'undefined'){
                var xhr = new ActiveXObject('Microsoft.XMLHTTP');
            }
            xhr.onreadystatechange = function() {
                if(xhr.readyState == 4 && xhr.status == 200){
                    alert(xhr.responseText);
                }
            }

            xhr.open("GET",'test.php?active='+text,true);//将数据以键值对的形式附在url尾部,多个键值对之间用‘&’连接
            xhr.send(null);
        }

 PHP:

$active = $_GET['active'];
if($active == 'login'){
    echo '{"key":"value"}';
}else {
    echo 'error';
}

但是get请求传递的数据都在url中所以安全性不高,需要发送数据一般用post请求,将请求数据通过send发送到服务器:

 1         var btn = document.getElementById('btn');
 2         btn.onclick = function () {
 3             var text = encodeURIComponent(document.getElementById('active').value);
 4             
 5             if(window.XMLHttpRequest != 'undefined'){
 6                 var xhr = new XMLHttpRequest();
 7             }else if(window.ActiveXObject != 'undefined'){
 8                 var xhr = new ActiveXObject('Microsoft.XMLHTTP');
 9             }
10             xhr.onreadystatechange = function() {
11                 if(xhr.readyState == 4 && xhr.status == 200){
12                     alert(xhr.responseText);
13                 }
14             }
15 
16             xhr.open("POST",'test.php',true);
17             xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");//设置头信息,以表单的形式发送
18             var str='active='+text;
19             xhr.send(str);
20         }

使用post请求发送数据时,服务器并不会像处理表单一样来处理收到的数据,所以要在send之前并且在open之后要通过setRequestHeader设置头信息,告诉服务器这是表单。 从性能角度看,post请求消耗的资源更多一点,get请求速度更快。

 3.超时设定

为XHR对象添加一个timeout属性来设置超时,当超过这个值时还未得到响应就会触发timeout事件并且会终止请求。

 

1 xhr.open("POST",'test1.php',true);
2             xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
3             var str = 'active='+text;
4             xhr.timeout = 1;
5             xhr.ontimeout = function() {
6                 alert("Request did not return in a second.");
7             }
8             xhr.send(str);

 

timeout属性和ontimeout事件要放在open之后send之前,不然ie会报错,并且只有ie8+支持。

 


4.进度事件

在浏览器接收新数据期间会周期性的触发progress事件。该事件接收一个event对象,对象包含三个二外属性:lengthComputable、loaded、total,分别表示进度信息是否可用,接收到的字节数和总字节数。下面是一个通过Ajax请求图片的例子:

 

 1 <button id="btn">获取信息</button>
 2 <div id="result"></div>
 3 <div id="picture"></div>
 4 <script>
 5 btn.onclick = function(){
 6     //创建xhr对象
 7     var xhr;
 8     if(window.XMLHttpRequest){
 9         xhr = new XMLHttpRequest();
10     }else{
11         xhr = new ActiveXObject('Microsoft.XMLHTTP');
12     }
13 xhr.onprogress = function(e){//监听progress事件来显示接收进度
14     e= e || event;
15     if(e.lengthComputable){
16         document.getElementById('result').innerHTML = '已接收:'+e.loaded+' /'+e.total;
17     }
18 }
19 xhr.onreadystatechange = function(){
20     if(xhr.readyState == 4 && xhr.status == 200){
21         var data = xhr.response;
22         var img = document.createElement("img");
23         img.src = URL.createObjectURL(data);    //创建一个指向data的url
24         img.onload = function() {
25             URL.revokeObjectURL(img.src);
26         }
27         document.getElementById('picture').appendChild(img);
28     }
29 }
30 xhr.open('GET','RYH.png',true);
31 xhr.responseType = 'blob';    //响应数据类型为二进制数据
32 xhr.send(null);
33 }
34 </script>    

 

 

 

这里的URL.createObjectURL(file | blob)传入一个file对象或blob(二进制对象)对象,创建一个指向该对象的URL。但是每次调用该方法时都会创建一个新的URL对象,即使指向的是同一个对象,所以每次创建完一个URL对象不再使用后要手动释放,通过URL.revokeObjextURL()来释放。

 

posted @ 2017-10-14 22:00  法克大叔叔  阅读(331)  评论(0编辑  收藏  举报