• 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个值
    statusText HTTP响应状态的说明


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

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


    在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>



  • 相关阅读:
    multiprocessing模块
    socket&socketserver网络编程
    collections模块
    socket模块
    网络基础知识
    迭代器,生成器,列表推导式,生成器表达式
    logging模块
    Module
    页面中公用的全选按钮,单选按钮组件的编写
    ajax
  • 原文地址:https://www.cnblogs.com/qigang/p/3841941.html
Copyright © 2020-2023  润新知