AJAX

来源:互联网 发布:youtube未连接到网络 编辑:程序博客网 时间:2024/06/05 17:08


AJAX是 AsynchronousJavaScript + XML 的简写。 这种技术能够向服务器请求额外的数据而无须卸载页面(即刷新),会带来更好的用户体验。

AJAX的核心为XMLHttpRequest对象(简称xhr),通过提供了向服务器发送请求和解析服务器响应提供了流畅的接口。能够以异步方式从服务器获取更多的信息, 这就意味着, 用户只要触发某一事件, 在不刷新网页的情况下,更新服务器最新的数据。X代表的是XML,但是用AJAX通信时数据与格式无关。

一 创建XMLHttpRequest对象

在很多浏览器中都可以直接创建xhr对象,但是在IE6中却还是要通过ActiveX的方式来创建xhr对象。检测浏览器支不支持直接创建方式,直接alert(typeof XMLHttpRequest),如果返回的是object则说明浏览器支持直接创建xhr对象。而IE6以及一下的浏览器中通过MSXML库来创建,可能会有三个版本。创建xhr对象的兼容方法:

</pre><pre code_snippet_id="352182" snippet_file_name="blog_20140518_1_1513540" name="code" class="javascript"><span style="font-size:18px;">function createXhr() {    if (typeof window.XMLHttpRequest != "undefined") {        return new XMLHttpRequest();    } else if (typeof ActiveXObject != "undefined") {        var version = ["MSXML2.XMLHttp.6.0",                        "MSXML2.XMLHttp.3.0",                        "MSXML2.XMLHttp"];        for (var i = 0; i < version; i++) {            try {                return new ActiveXObject(version[i]);            } catch (e) {            }        }        throw new Error("您的操作系统或者浏览器不支持XHR对象");    } else {        throw new Error("您的操作系统或者浏览器不支持XHR对象");    }}</span>


二 使用xhr对象

在上面创建了xhr对象以后,如果要和浏览器进行通信还必须调用两个方法:open()和send()方法。

xhr.open(x1,x2,x3); 这个方法是用来启动一个请求,准备发送数据,三个参数:参数一是提交方式(get或者post);参数二是请求的目标页面,也就是请求的服务器处理程序页面;参数三是一个布尔值,表示同步还是异步,true表示异步请求,false表示同步请求。

xhr.send(x1); 这个方法是真正的数据请求方法,执行这个方法后,数据请求就会提交到服务器中。接收一个参数,作为向服务器请求提供的数据主体,如果不需要则填写null即可,并且必须填写,不能够为空。

当执行send()方法将请求发送出去,然后接到服务器的响应后,会将响应结果自动填充到xhr的属性中,xhr一共有四个属性,意义如下:

属性说明responseText作为响应的主体返回的文本内容responseXML如果响应的数据类型是“text/xml”或者“application/xml”,这返回的是XML 文档status响应的HTTP状态,N个值statusTextHTTP响应状态的说明

属性status有很多值,代表了服务器响应的各种状态,简单的几个如下:

状态值状态字符串说明200OK服务器成功的返回了数据400Bad Request语法错误,导致服务器端无法识别404Not Found指定的URL在服务器端找不到500Internal Server Error服务器端遇到无法处理的错误,占时不能够完成数据请求503ServiceUnavailable 由于服务器过载或维护导致无法完成请求

在send()方法发送完成后,就只是需要监听xhr对象的status对象的值,最好是用状态码,对于状态值在跨浏览器的时候可能不一致。如果收到的值为200,则代表服务器端正确的响应了请求。

<span style="font-size:18px;">//用事件注册函数给按钮btnOne添加了一个点击事件addEvent(btnOne,'click',function(){var xhr = createXhr();xhr.open("get","one.ashx",false);//设置为同步xhr.send(null);//当我们发送完成后,如果服务器有数据返回,会自动填充对象XMLif(xhr.status == 200){//状态码,200表示成功返回数据,其它都是出错alert(xhr.responseText);//作为响应主体返回的文本alert(xhr.responseXML);//如果响应主体内容类型是"text/xhr"或"application/xml",则返回包含响应数据的 XML DOM 文档alert(xhr.status);//返回的HTTP状态alert(xhr.statusText);//返回的是HTTP状态说明,可能有的浏览器不一样}else{alert("返回数据失败:状态码:"+xhr.statue+"状态说明:"+xhr.statueText);}})</span>

三 同步和异步

在上面的xhr对象使用中采用的是同步的请求数据的方式。同步请求数据固然简单容易,但是和XML对象的请求一样,同步时会造成堵塞以及缓慢的状况。所有异步才是使用更多的方式。

异步请求中,需要添加一个事件,readystatechange,和请求XML内容一样,这个事件中有一个属性readyState,有几个值,相比请求XML对象文档的时候多了一个:

状态说明0未初始化尚为调用open()方法,这个值是在open()方法调用之前会输出1启动已经调用open()方法,但是还没有调用send()方法2发送已经调用send()方法,还没有接收到数据的响应3接收已经收到部分数据的响应,还不可以使用4完成已经接收到全部的数据响应,而且可以使用

同步请求方式:

见上面一段代码

异步请求方式:

异步请求数据的时候,在readystatechange事件中,监听readyState的值,是否为4,如果为4就代表数据接收完成,然后就可以进行数据的处理,但是这个事件的方法必须要写在send()方法之前,也就是需要先注册事件。而且在send()方法调用之前还可以通过xhr.abort()方法来取消异步请求,放在send()方法之前会报出一个错误,放在 放在 responseText之前会得到一个空值。

<span style="font-size: 18px;">addEvent(btnTwo,"click",function(){<span style="white-space:pre"></span>var xhr = createXhr();//异步中的事件,必须写在前面,状态1~4和XML中的1~4是一样的,多了一个0,表示还没有发送xhr.onreadystatechange = function(){if(xhr.readyState == 4){//表示响应已经接收完成,而且可以使用数据if(xhr.status == 200){//表示服务器正确返回了页面,一切OKalert(xhr.responseText);}else{alert("数据接收出错");}}else{}}xhr.open("get","one.ashx",true);//异步提交//xhr.abort();//用来取消请求异步提交,这个必须写在send前面,而且如果取消后会抛一个异常xhr.send(null);//必须要写在事件后面})</span>

四 GET和POST

在提供服务器请求的过程中,有两种方式,分别是:GET 和 POST。在 Ajax 使用的过程中,GET 的使用频率要比 POST 高。

每一次向服务器请求服务以及服务器返回服务结果的时候,都会包含一个HTTP头信息,这是浏览器和服务器自动添加的,在请求服务的时候,我们可以设置HTTP头信息,但是不能够读取,在接收到服务器的响应后,可以获取HTTP头信息,但是不能够设置HTTP头信息

获取单个HTTP头信息的方式:xhr.getResponseHeader("Content-Type");获取HTTP响应信息中的Content-Type属性的值

获取所有HTTP头信息的方式:xhr.getAllResponseHeaders();

设置HTTP头信息的方式:xhr.setResquestHeader("name","value");在HTTP响应的头信息中就会添加一行:name:value,可以通过fireBug等浏览器调试工具来查看

Get请求:

GET 请求是最常见的请求类型,最常用于向服务器查询某些信息。必要时,可以将查询字符串参数追加到 URL 的末尾,以便提交给服务器。如果参数中存在一些特殊字符则需要通过encodeURIComponent来进行编码,Get请求的时候,参数时通过URL 后的问号给服务器传递键值对(name=value)数据,每一组数据之间用 & 来分割,服务器接收到返回响应数据,send()方法中参数值为null。

<span style="font-size:18px;">addEvent(btnOne,"click",function(){var xhr = createXhr();var url = "one.ashx?rand="+Math.random();//添加一个随机数url = encodeUrl(url,"id","10002");url = encodeUrl(url,"name","ab$cd");//编码主要就是针对这种特殊字符和中文xhr.onreadystatechange = function(){if(xhr.readyState == 4){if(xhr.status == 200){alert(xhr.responseText);}else {alert('获取数据错误!错误代号:' + xhr.status + ',错误信息:' + xhr.statusText);}}}xhr.open("get",url,true);xhr.send(null);})//对参数进行一个编码function encodeUrl(url,key,value){url += url.indexOf('?') >=0 ? '&':'?';//判断URL中是否包含 ? 号url += encodeURIComponent(key)+"="+encodeURIComponent(value);return url;}</span>

Post请求:

Post请求可以向服务器发送很多的数据,一般在表单的提交上都用的是Post请求方式。Post请求的时候,参数不会跟在URL的后面,而是通过 & 来分割键值对,这个一个字符串整体在send(date);方法中传递给服务器。但是, 向服务器发送 POST 请求由于解析机制的原因, 需要进行特别的处理, 因为POST 请求和 Web 表单提交是不同的,需要使用 XHR 来模仿表单提交。在open()方法之后在send()方法之前需要对请求头进行一个设置,添加一句:xhr.setRequestHeader("Conent-Type","application/x-www-form-urlencoded");

<span style="font-size:18px;">addEvent(btnTwo,"click",function(){var xhr = createXhr();var url = "one.ashx?rand="+Math.random();var date = "";date = encodeUrl(date,"id","10021");date = encodeUrl(date,"name","23%ge");xhr.onreadystatechange = function(){if(xhr.readyState == 4){if(xhr.staus == 200){alert(xhr.responseText);}else{alert("请求出错:状态码:"+xhr.status+" 状态说明:"+xhr.statusText);}}}xhr.open("post",url,true);//Post访问需要设置头信息xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");xhr.send(date);})<span style="white-space:pre"></span>//编码数据function encodeUrl(date,key,value){date += date.length>0?'&':"";date += encodeURIComponent(key);date += "=";date += encodeURIComponent(value);return date;}</span>

从性能上面来说,GET比Post提交效率要高出很多,相同的数据量下,GET要比POST快上近两倍。

同样,JSON格式的数据也可以通过AJAX来请求:

<span style="font-size:18px;">addEvent(btnThree,"click",function(){var xhr = createXhr();var url = "demo.json?rand"+Math.random();//添加一个随机数,防止访问缓存的数据xhr.onreadystatechange = function(){if(xhr.readyState == 4){if(xhr.status == 200){alert(xhr.responseText);var json = JSON.parse(xhr.responseText);alert(json);}}}xhr.open("get",url,true);xhr.send(null);})</span>

三 封装AJAX

封装AJAX时,几个问题:参数多少;请求方式是GET还是POST,同步还是异步。为了解决上面几个方法,传递一个对象过去,这个对象中的包含了请求方式,数据(也是一个对象),同步还是异步,同时还包含一个回调函数。封装的方法是慢慢来修改而成的,不是一次形成

回调函数:封装以后,请求数据的结果是不能够返回的,因为涉及到作用域的问题,作用域是无法返回的。故在传递的参数中,添加一个回调函数,这个回调函数接收一个参数,在封装好的AJAX方法中,当正确接收服务器端的响应数据后,调用这个回调函数,将返回的结果传递到这个回调函数中即可,这样在操作这个返回结果是在调用封装好Ajax方法

封装Ajax:

<span style="font-size:18px;">//封装AJAXfunction ajax(box) {    var xhr = createXhr();    if (box.method === "get") {        box.url += box.url.indexOf('?') < 0 ? "?" : "&";        box.url += getDate();    }    if (box.async === true) {        xhr.onreadystatechange = function () {            if (xhr.readyState == 4) {                callBack();            }        }    }    xhr.open(box.method, box.url, box.async)    if (box.method === "post") {        xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");        xhr.send(getDate());    } else {        xhr.send(null);    }    if (box.async === false) {callBack();    }//下面俩个方法写在这个Ajax方法中,使封装更好,只是需要调用一个方法即可,但是getDate方法的使用范围就缩小了    //回调方法:这里面主要是判断,数据是否正确接收,多次使用故封装起来    function callBack() {        if (xhr.status == 200) {            //return xhr.responseText   返回的是为空,因为不能够返回作用域            //通过函数的回调来实现结果的返回            box.success(xhr.responseText);//        } else {            box.success("error;状态码:" + xhr.status + ";状态码解释:" + xhr.statusText);        }    }    //名值对编码函数    function getDate() {        var arr = [];        for (var i in box.date) {           arr.push(encodeURIComponent(i) + "=" + encodeURIComponent(box.date[i]));       }       return arr.join("&");    }}</span>

调用Ajax:

<span style="font-size:18px;">//调用window.onload = function () {    var btnOne = document.getElementById("btnOne");//点击按钮的时候请求数据    btnOne.onclick = function () {        var box = {            method: "post",            url: "one.ashx",            date: {                "name": "abcd",                "age": 100            },            async: true,            //用作回调函数,在这里面来操作返回的结果            success: function (res) {                //alert(res);                //若返回的数据位JSON格式                var par = JSON.parse(res);                alert(par[0].title);            }        }        ajax(box);    }}</span>


0 0