JavaScript系列----AJAX机制详解以及跨域通讯

1.Ajax

1.1.Ajax简介

  Ajax简介这一部分咱们主要是谈一下ajax的起源,ajax是什么?由于这些是跟技术无关的。因此,大多细节都是一笔带过。php

  Ajax的起源?html

  Ajax一词源于2005年 Jesse James Garrett发表的一篇题为"Ajax:A new Approach to Web Applications".他在这篇文       章中介绍了一种新技术,用他的话说,就是Ajax :Asynchronous JavaScript +XML的缩写。前端

  Ajax是什么?ajax

  这种新技术的主要目的就是为了使前端网页可以向服务器请求额外的数据而不须要卸载页面。自从这种技术出现之后,微软率先引入XHR对象(ajax可以实现的核心对象),而后其余浏览器相继实现这种技术。总而言之,ajax就是一种能异步通讯的技术。json

1.2.Ajax的核心对象---XMLHttpRequest

  由于IE5是最早引入这个XHR对象的,当时并无事实上的标准。在IE中有三种不一样的XHR对象版本:MSXML2.XMLHttp,MSXML2.XMLHttp.3.0MSXML2.XMLHttp.6.0;跨域

根据这三种版本号,在IE中建立一个XHR对象以下:浏览器

function createXHR() { //IE7以前的版本经过这种方式  var versions = [
    'MSXML2.XMLHttp',
    'MSXML2.XMLHttp.3.0',
    'MSXML2.XMLHttp.6.0'
  ];
  var xhr = null;
  for (var item in versions) {
    try {
      xhr = new ActiveXObject(item); //若不存在该版本,可能会出错
      if (xhr) break;
    } catch (e) {
      //通常对这种错误不作处理
    }
  }
  return xhr;
}

在IE引入这个对象以后,其余浏览器厂商也相继跟随,这时候XHR对象成为事实上的标准!安全

跨浏览器建立XHR对象;服务器

function createXHttpRequest() {
  if (typeof XMLHttpRequest !== 'undefined') { //不要用 if(XMLHttpRequest){}这种形式, return new XMLHttpRequest();              //若是是这种形式在找不到XMLHttpRequest函数的状况下,会报错。
} else if (typeof ActiveXObject !== 'undefined') { 
return createXHR(); //用到刚才咱们建立的函数
}
else { throw new Error('不能建立XMLHttpRequest对象'); } }

 

1.2.XMLHttpRequest的用法

XMLHttpRequest对象的函数有6个:cookie

open("method",url,boolean);
//该方法的三个参数,分别为----提交方式"get"或者"post"等
                //&& url是相对于执行代码的当前页面的路径(使用绝对路径是容许的)&&是否异步

send();
//这个方法接收一个参数,这个参数是做为请求主体发送的数据,
//说明: 若是有参数,请使用post方式提交 使用方式以下,send("user="+username+"&pwd="+password); //若是没有参数,为了兼容性考虑,必须在参数中传入null,即send(null);该方式使用get方式提交

abort();             //取消当前响应,关闭链接而且结束任何未决的网络活动。

                    //这个方法把 XMLHttpRequest 对象重置为 readyState 为 0 的状态,而且取消全部未决                         //的网络活动。例如,若是请求用了太长时间,并且响应再也不必要的时候,能够调用这个方法。

 

getResponseHeader()     

                    //返回指定的 HTTP 响应头部的值。其参数是要返回的 HTTP 响应头部的名称。可使用任                         //何大小写来制定这个头部名字,和响应头部的比较是不区分大小写的。

                    //该方法的返回值是指定的 HTTP 响应头部的值,若是没有接收到这个头部或者 readyStat                          //e 小于 3 则为空字符串。若是接收到多个有指定名称的头部,这个头部的值被链接起来并                          //返回,使用逗号和空格分隔开各个头部的值。

getAllResponseHeaders()              

                   //把 HTTP 响应头部做为未解析的字符串返回。

                   //若是 readyState 小于 3,这个方法返回 null。不然,它返回服务器发送的全部 HTTP 响应的

                   //头部。头部做为单个的字符串返回,一行一个头部。每行用换行符 "\r\n" 隔开。

                         

setRequestHeader()

                  //向一个打开但未发送的请求设置或添加一个 HTTP 请求。

 

  XMLHttpRequest对象的属性有5个:

属性 描述
responseText 做为响应主题被返回的文本
responseXML 若是相响应的是text/html或者application/xml类型的话,这个属性将保存着响应的XML文档
status http的响应状态码
statusText http状态的说明
readyState XMLHttpRequest对象的状态位 0 1 2 3 4 分别表示5种状态
timeout 设置超时时间,单位是ms.目前只有IE8+支持---还没有标准化(不推荐使用)

 

  XMLHttpRequest对象的事件属性onReadyStateChange:-----全部浏览器兼容

  该属性监听的是  XMLHttpRequest对象的readyState属性的变化: 

  readyState的变化分别对应以下状态:

  0:还没有初始化。未调用open()以前

  1:启动。调用open()以后,可是未调用send();

  2:发送。调用send()可是还没有获得响应。

  3:正在接收数据。刚接收到响应数据开始到接收完成以前。

  4: 完成。数据接收完成。

 

xhr.onreadystatechange = function () {
  if (xhr.readyState == 4) {
    if (xhr.status >= 200 && xhr.status <== 300 || xhr.status == 304) {
      alert(xhr.responseText);
      //处理接收的数据
    } else {
      //请求失败,未获得响应数据
    }
  }
}; //补充说明:注册事件必须发生在send()之前

 

XMLHttpRequest对象的事件属性ontimeout -----仅限IE8+,不过最新的主流高版本浏览器也已经实现(不推荐使用)

xhr.timeout=1000;//一秒钟

xhr.ontimeout=functon(){
  //处理代码
  ......
}

  这种使用方式有个问题须要注意,就是在超时以后,在接收到数据后仍然会触发onreadystatechange事件,若是在处理onreadychange事件时访问xhr.status属性,会出错。因此咱们在访问该属性时须要作一下try{}catch处理。可是,由于这个属性暂不兼容,全部咱们就不重点讲了。

 

XMLHttpRequest对象的事件属性onload onerror onloadstar onbort onprogress

                                                                                                   -----非IE浏览器和IE 10+已实现

       onload在IE8以上能够实现,大部分事件根据readySate变化都可以实现,以上事件只不过是方便使用而已。

 

  onload和onprogress 这两种事件分别对应着readyState=4和readyState=3的状况,使用方式分别以下: 

     xhr.onload= function (event) {
            //event只包含一个属性 event.target=xhr;使用方式只是在readyState=4时差很少..
        }
     xhr.onprogress=function(event){
         //event除了包含event.target=xhr以外,还包含三种属性
         //lengthComputale(进度信息是否可用),position(已接受字节数)和totalSize(总字节数).
         
     }

补充:有些事件都可以根据readyState的状态进行模拟。只有有的浏览器进行了方便化处理而已。  

 

3.单向跨域技术 ---CORS

 今天咱们这里讲的是客户端网页向不在同一个域的服务器请求数据..客户端在收到返回的数据时时,用回调函数处理数据。

即:

 1. 客户端向域外服务器请求数据

 2.服务器获得响应后向客户端发送数据。

 3.客户端根据返回的数据执行回调函数.

 

 我知道不一样域下的iframe也能够进行通讯,并且这也是一种跨域通讯技术。可是,这种iframe页面之间的双向通讯,咱们在下一个专题里面讲解,今天主要讲的是单向通讯。

3.1.CORS跨域请求的原理

在用xhr(XMLHttpRequest)对象或者xdr(XDomainRequest)对象,发送域外请求时,大概的实现原理以下图:

 3.2.IE中CORS技术的实现

 IE8引入了一个XDR类型,这个类型与XHR基本相似,可是其能实现安全可靠地跨域通讯。

 XHD的特色:

 1.cookie不会随请求发送,也不会随响应返回。

 2.只能设置请求头部中的Content-Type片断。

 3.不能访问响应头部信息。

 4.只是支持get和post请求。

 

 XDR支持onload和onerror事件属性,且其使用方式和XHR基本一致,不过其open()只接收两个参数,默认是异步的。

var xdr = new XDomainRequest();
xdr.onload = function () {
  //处理xdr.responseText
}
xdr.onerror = function () {
};
xdr.open('get', '绝对url');
xhr.send(null);

 

 

3.3.跨浏览器的CORS技术实现

在标准浏览器中XHR对象就已经能够自动实现跨域请求,可是XHR和XDR的不一样之处:

1.XHR能够在设置 withCredentials =true时,浏览器会把cookie发送给服务器,服务器此时经过设置头部Access-Control-Allow-Credentials:true时来响应。若是,服务器不设置这个属性,则浏览器会触发onerror事件。

2.在回调函数中能够访问status和statusText属性,并且支持同步请求。

 如下是实现跨域请求的代码:

function createCrosRequest(method, url) {
  var xhr = new XMLHttpRequest(); //IE7+
  if ('withCredentials' in xhr) { //IE8-IE9浏览器没有这个属性
    xhr.open(method, url, true);
  } else if (typeof XDomainRequest != 'undefined') {
    xhr = new XDomainRequest();    //IE
    xhr.open(method, url)
  }
  return xhr;
}
var request=CreateCrosRequest("get","url");
if(request){
request.onload=function(){
//处理request.responseText;
}
request.send(null);
}

4.单向跨域技术 ---JSONP技术

 JSONP技术比较简单,其主要原理主要是利用script标签的特性。

 script标签和image标签同样,它们都具备src属性,并且这个属性是可跨域的。

 

由于script标签返回的都是js代码,且该js代码会自动执行。因此,若是咱们请求返回的数据也是相似一段js代码的形式,岂不是就能够实如今脚本加载完毕后自动执行。

若是咱们的请求,返回的数据是 callback + '(' + json + ')'; 这种形式的数据, 那么在脚本加载完毕以后也就能自动执行callback()函数了.

4.1.客户端写法

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body>
       <button id="button">请求数据</button>
</body>
<script>
    window.onload=function(){
        var button=document.getElementById("ibutton");
        function callback(data){
            //处理data
        }
        button.onclick=function(){
            var script=document.createElement("script");
            script="http://www.sasd.com/json/?callbak=callback"; 
            document.body.insertBefore(script,document.body.firstChild);//加载脚本
            
        }
        
    }
</script>
</html>

   1.客户端将回调函数名写入<Script>脚本的url参数中。

   2.script加载的时候会发送跨域请求。

4.2.服务器端

 1.经过url获得函数名,命名为callback

 2.将请求的数据做为函数的参数格式转化json格式,命名为。

 3.将返回结果拼接为 callback+"("+json+")"; --------返回的就是填充式的数据,这段数据在脚本中会自动执行。

 4.返回数据.

 

 4.3.JSONP技术的缺点

 1.由于是经过url传参数,因此请求只能是get类型的。

 2.<script>目前只有onload属性事件,onerror尚未统一化,若是加载脚本出错,客户端很可贵到反馈。

 3.所请求数据的站点必须是可信任的,若是返回的数据段中注入的有恶意的代码,危害较大,且难以发现。

相关文章
相关标签/搜索