AJAX


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);
		//当我们发送完成后,如果服务器有数据返回,会自动填充对象XML
		if(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){	//表示服务器正确返回了页面,一切OK
					alert(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;">//封装AJAX
function 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>



 

 

转载于:https://www.cnblogs.com/qigang/p/3841941.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值