ajax从入门到深入精通

来源:互联网 发布:python cmdb源码 编辑:程序博客网 时间:2024/05/21 21:37

前言

ajax全称Asynchronous Javascript and XML。其中Asynchronous代表异步。同步于异步是描述通信模式的概念,同步机制:发送方发生请求后,需要等待接收到接收方的响应后,才能处理其他的业务。异步机制:发送方发生一个请求后,可以接着处理其他业务,不需要等待。同步机制主要是为了保证数据的一致性,异步主要是为了提高效率。
  • 1
  • 2

ajax包含的技术与原理

  1. 使用CSS和XHTML来表示。
  2. 使用DOM模型来交互和动态显示。
  3. 使用XMLHttpRequest来和服务器进行异步通信。
  4. 使用javascript来绑定和调用。

在上面几种技术中,除了XmlHttpRequest对象以外,其它所有的技术都是基于web标准并且已经得到了广泛使用的,可见ajax核心技术应该是XMLHttpRequest对象了。Ajax的原理,简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。所以我们主要弄清楚以下问题,也是本文主要解决的问题

  • 怎样创建xmlHttpRequest对象?
  • 怎样通过get、post传递传递数据?
  • 怎样控制http头信息?
  • 通过ajax能传递什么格式的数据?
  • 怎样接收服务器传递的数据?
  • 怎样控制数据接收的进度?
  • 如果控制数据传递过程中的错误?
  • 关于跨越传输的问题?

ajax简单实现

为了便于理解,我从执行过程的角度绘制了下图来解析ajax处理流程
这里写图片描述

创建xmlHttpRequest对象

因为各大浏览器厂商为了利益之争,导致了我们开发者创建xmlHttpRequest对象面临兼容性问题。

function CreateXmlHttp() {    if (window.XMLHttpRequest)    {// code for IE7+, Firefox, Chrome, Opera, Safari      xmlhttp=new XMLHttpRequest();    }else{// code for IE6, IE5      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");    }    }var xmlhttp=null;CreateXmlHttp();//创建xmlHttpRequest对象console.log(xmlhttp);//在控制台输出xmlhttp对象
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

通过输出xmlhttp,我们可以查看到XMLHttpRequest对象以及其原型中包含的方法。
xmlHttpRequest对象包含的属性和方法
xmlHttpRequest原型包含的方法

ajax请求实例

index.php代码如下

<meta charset="utf-8"><script type="text/javascript">function CreateXmlHttp() {    if (window.XMLHttpRequest)    {// code for IE7+, Firefox, Chrome, Opera, Safari      xmlhttp=new XMLHttpRequest();    }else{// code for IE6, IE5      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");    }    }var xmlhttp=null;CreateXmlHttp();//创建xmlHttpRequest对象xmlhttp.onreadystatechange=function(){//设置状态发生变化时候监听函数    switch(xmlhttp.readyState){        case 1://调用了open的方法            console.log('调用了open的方法,xmlhttp.readyState=1');        break;        case 2://调用了send方法            console.log('调用了send方法,,xmlhttp.readyState=2');        break;        case 3://正在接受数据            console.log('正在接受数据,xmlhttp.readyState=3');        break;        case 4://数据接收完成            if(200 == xmlhttp.status){                console.log("xmlhttp.readyState=4,请求的数据为:"+xmlhttp.responseText);                           }else{            }        break;    }    console.log(xmlhttp);}xmlhttp.open("get", "http://127.0.0.1/a2.php", true);//调用open的方法初始化xmlhttp.send();//调用send方法发送数据</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

a2.php文件如下:

<?phpfor ($i=0; $i<5  ; $i++) {     var_dump('expression'.$i);}
  • 1
  • 2
  • 3
  • 4

执行结果如下:
ajax实例执行结果

在论同步异步比较

在上面实例中,调用open方法采用的是异步方式去调用,现在我们将其改成同步方式调用,比较两者差异
为了便于比较将上面实例代码改为:

xmlhttp.open("get", "http://127.0.0.1/a2.php", true);//调用open的方法初始化console.log("************"+xmlhttp.readyState+"************");xmlhttp.send();//调用send方法发送数据console.log("************"+xmlhttp.readyState+"************");
  • 1
  • 2
  • 3
  • 4

调用结果
异步调用结果
现在测试同步调用,只主要讲open方法改为如下:

xmlhttp.open("get", "http://127.0.0.1/a2.php", false);//调用open的方法初始化
  • 1

调用结果
同步调用结果
总结:同步与异步调用差别还是挺大的。为什么会有这样的差异呢?在同步调用中,因为浏览器调用了xmlhttp调用了send方法后,就陷入了等待服务器数据返回状态,不能进行其他的操作,等服务器返回后,直接将xmlhttp的readyState属性改了4,也就是说同步调用中,xmlhttp的readyState值直接从1跳到了4。对于异步调用,调用了send方法后,不需要等待,直接就执行了下面的代码,不需要等待。当服务器返回数据时候,就回调onreadystatechange对应的方法。

ajax进度控制

进度事件简述

在不懂ajax进度控制的时候,当看到网页中,别人实现的加载进度条,总是感觉好高达上,其实现其实并不是很难。首先我们需要了解其涉及到了6个进度事件。
- loadstart:在接收到相应的数据的第一个字节时候触发。
- progress:在接受相应期间持续不断触发,这个事件大概每50毫秒执行一次。
- error:在请求发送错误时触发
- abort:在因为调用abort()方法而终止连接时候触发
- load:在接收到完整的相应数据时触发
- loadend:在通信完成或者是触发error、abort或load事情后出发
- timeout:如果指定了timeout值,在指定时间段内未完成请求时触发。
现在我们从事件触发的角度去看,ajax通信,首先触发Loadstart事情,接下来是一个或多个progress事情,然后触发error、abort或load事情中的一个,最后以触发loadend事情结束。
为了测试以上事件,我们先做一个测试,代码如下

<meta charset="utf-8"><script type="text/javascript">Object.prototype.addListener=function(ev,fn){    if (this.attachEvent) {        this.attachEvent('on' + ev, fn);    }else{         this.addEventListener(ev,fn,false);    }}function CreateXmlHttp() {    if (window.XMLHttpRequest)    {// code for IE7+, Firefox, Chrome, Opera, Safari      xmlhttp=new XMLHttpRequest();    }else{// code for IE6, IE5      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");    }    }var xmlhttp=null;CreateXmlHttp();//创建xmlHttpRequest对象//绑定事件,是我addListener自定义兼容各浏览器的绑定事件方法xmlhttp.addListener('loadstart',function(){checkInfo('loadstart')});xmlhttp.addListener('progress',function(){checkInfo('progress')});xmlhttp.addListener('error',function(){checkInfo('error')});xmlhttp.addListener('abort',function(){checkInfo('abort')});xmlhttp.addListener('load',function(){checkInfo('load')});xmlhttp.addListener('loadend',function(){checkInfo('loadend')});xmlhttp.open("get", "http://127.0.0.1/a2.php", true);//调用open的方法初始化xmlhttp.send();//调用send方法发送数据function checkInfo(fnName){    console.log(fnName+'事件被触发,xmlhttp.readyState='+xmlhttp.readyState);}</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

执行结果如下
这里写图片描述
通过执行结果,正好证实了,我们上面的事件触发的论述。

ajax进度条实例

现在要开始写ajax进度条了,好久没有写过进度条,还是有点小激动。
代码如下:

<meta charset="utf-8"><script type="text/javascript">Object.prototype.addListener=function(ev,fn){    if (this.attachEvent) {        this.attachEvent('on' + ev, fn);    }else{         this.addEventListener(ev,fn,false);    }}function CreateXmlHttp() {    if (window.XMLHttpRequest)    {// code for IE7+, Firefox, Chrome, Opera, Safari      xmlhttp=new XMLHttpRequest();    }else{// code for IE6, IE5      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");    }    }var xmlhttp=null;window.onload=function(){    var loadbutton=document.getElementById('loadbutton');    loadbutton.addListener('click',function(){        CreateXmlHttp();//创建xmlHttpRequest对象        //绑定事件,是我addListener自定义兼容各浏览器的绑定事件方法        xmlhttp.addListener('loadstart',loadstart);        xmlhttp.addListener('progress',progress);        xmlhttp.addListener('load',load);        xmlhttp.addListener('loadend',function(){console.log('执行结束了');});        xmlhttp.open("get", "http://127.0.0.1/ceshi.pdf", true);//调用open的方法初始化(为了便于查看效果,我让其加载一个比较大的文件,因为最开始,我尝试使用一个php文件但是看不到效果,因为它立刻出现结果)        xmlhttp.send();//调用send方法发送数据    }); }//处理开始接受数据的画面function loadstart(){    //当开始加载的时候,将defaultCont隐藏,将progressBox显示出来    document.getElementById('defaultCont').style.display="none";    document.getElementById('progressBox').style.display="block";}//处理进度function progress(event){    //修改progressTest里面的文本提示信息以及progress的长度    var progressTest=document.getElementById('progressTest');    var progress=document.getElementById('progress');    if (event.lengthComputable) {//判断响应文本是否可以计算长度        var recivedSize= event.position;//已经接收的字节数        var totalSize=event.totalSize;//根据Content-Length相应头部确定的预期字节数        progressTest.innerText=(recivedSize/totalSize*100 )+"%";        progress.style.width=600*(recivedSize/totalSize)+"px";// 为什么是600,因为包含它的容器长度为600    }}//处理加载完成function load(event){    //当开始加载的时候,将defaultCont显示出来,并将服务器返回的结果放在其里面,并将progressBox隐藏掉    document.getElementById('progressBox').style.display="none";    var defaultCont=document.getElementById('defaultCont')    defaultCont.style.display="block";      //因为加载的是一个pdf文件,所以不需要将其显示在页面上,我直接输出了xmlhttp对象    console.log(event.target);    //defaultCont.innerText=event.target.responseText;//备注,其中event.target为xmlhttp对象     //使用innerText代替innerHTML更加安全,因为如果使用innerHTML,responseText中包含html代码或JavaScript代码时候,浏览器不会解析,如果你需要其解析,当然得用innerHTML。}</script><div style="width:600px; height:auto;margin:0 auto">    <input type="button" id="loadbutton" value="加载">    <div id="defaultCont">        <img src="1.jpg" width="600px">    </div>    <div id="progressBox" style="display:none;position:relative">        <div>已经加载了:<span id="progressTest">0</span></div>        <div id="progress" style="position:absolute; width:0px; top:35px; left:0;z-index:10; height:35px; background-color:#F00"></div>        <div style="position:absolute; width:600px; top:35px; left:0; z-index:1;height:35px; background-color:#040"></div>    </div></div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

执行效果截图如下
这里写图片描述
这里写图片描述
这里写图片描述

ajax跨域控制

我们如果把xmlhttp的open方法改为如下:

xmlhttp.open("get", "http://localhost/a2.php", true);
  • 1

在我们执行页面的时候,如果我们在服务端不进行相应的设置,就会出现如下效果:
这里写图片描述
这提示我们服务器端禁止我们跨域(跨源)请求。我们可以通过再服务端对Access-control-Allow-origin进行配置,来限定哪些域名可以访问。如果设置Access-control-Allow-origin:*代表所有的

<?phpheader("Access-control-Allow-origin:*");//允许的域名for ($i=0; $i<5  ; $i++) {     var_dump('expression'.$i);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

然后执行代码就okey了

补充

到这里,关于ajax涉及到的主要内容基本上说完了,现在说点没有提到的。

  • 设置头信息
    通过setRequestHeader设置头信息,通过getAllResponseHeaders获取所有头信息,通过getResponseHeader获取指定的头信息。
    比如:
xmlhttp.setRequestHeader("Accept-Language","zh-cn,zh;q=0.5");
  • 1
  • ajax能传递什么格式的数据
    ajax从本质上面来说就是一个请求,所以所有的类型都是支持的,平常看到说比如jquery要指定一个dataType,其实是jquery库对请求回来的response进行了预解析,序列化成对应的数据类型给,比如有服务端有个json,然后的dataType指明为text,其实返回给的还是那些内容,只是没有给序列化而已。
  • ajax中表单对象FormData使用
    formData对象是html中form表单的抽象。其中有一个重要的方式是append,用于向formData表单对象中插入数据。
    直接看如下代码(很多代码如上面雷同,就不再粘贴)
window.onload=function(){    var loadbutton=document.getElementById('loadbutton');    loadbutton.addListener('click',function(){        CreateXmlHttp();//创建xmlHttpRequest对象        //绑定事件,是我addListener自定义兼容各浏览器的绑定事件方法        xmlhttp.addListener('loadstart',loadstart);        xmlhttp.addListener('progress',progress);        xmlhttp.addListener('load',load);        xmlhttp.addListener('loadend',function(){console.log('执行结束了');});               var data=new FormData();        data.append('name','dequan');        xmlhttp.open("post", "http://127.0.0.1/a2.php", true);//调用open的方法初始化(为了便于查看效果,我让其加载一个比较大的文件,否则看不到效果)        xmlhttp.setRequestHeader("Accept-Language","zh-cn,zh;q=0.5");        xmlhttp.send(data);//调用send方法发送数据    }); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

a2.php代码如下

<?phpvar_dump($_POST);
  • 1
  • 2

结果截图如下:
这里写图片描述

原创粉丝点击