zoukankan      html  css  js  c++  java
  • 浅谈JavaScript中的Ajax

    引言

      作为一名WEB开发者,我想Ajax技术是一定需要掌握的。你也许平时没有使用JavaScript真正的写过Ajax。但是你一定使用过JQuery里面的相关函数来进行异步调用。今天我们就来介绍下原生Ajax的技术。

    XMLHttpRequest对象

      说到原生的Ajax技术实现,XMLHttpRequest对象是肯定是需要介绍的。历史上IE5是第一个支持XHR的浏览器,在IE5中,XHR对象是通过MSXML库中的一个ActiveX对象来实现的。因此在IE5,IE6中可能会遇到3种不同版本的XHR对象。为了在低版本IE中可以稳定的创建XHR。我们可以使用以下函数来创建。请看代码:

     1 /**
     2  * 通过XMLHttpRequest来了解Ajax技术的本质.
     3  * 作为约定俗成的准则,JS中构造函数以大写字母开头
     4  **/
     5 function AjaxInstance() {
     6     this.xmlhttprequest = function () {
     7         if (typeof XMLHttpRequest !== "undefined") {
     8             return new XMLHttpRequest();
     9         //适用于IE7之前的版本
    10         } else if (typeof ActiveXObject !== "undefined") {
    11             if (typeof arguments.callee.activeXString !== "string") {
    12                 var versions = ["MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP"];
    13                 for (var i = 0, len = versions.length; i < len; i++) {
    14                     try {
    15                         arguments.callee.activeXString = versions[i];
    16                         return new ActiveXObject(versions[i]);
    17                     } catch (e) { }
    18                 }
    19             }
    20             return new ActiveXObject(arguments.callee.activeXString);
    21         }
    22         else {
    23             alert("您的浏览器版本不支持Ajax技术,请升级新版本浏览器...");
    24         }
    25     }
    26 }

      在例子中我们看到,在IE7之前的版本中,创建XHR对象,需要3个库。并且早期IE中XHR对象实质是ActiveXObject对象。

      注意:IE7+,Chrome,Firefox,Opera,Safiri都是原生支持XMLHttpRequest对象的。所以在这些浏览器中只需要像第4行代码一样new一个对象即可。

    XHR的用法

      在使用XHR对象时,要调用的第一个方法是open()。该方法接收3个参数,它们分别是:要发送的请求的类型(get,post)、请求的URL以及表示是否异步发送请求的布尔值。例如:

    1 this.xmlhttprequest.open(method, url, true);

      有两点需要说明:1、URL是相对于执行代码的当前页面。2、调用open方法并不会立即发送请求,而是启动一个请求以备发送。

      注意:只能向同一个域中使用相同端口和协议的URL发送请求。如果URL与启动请求的页面有任何的差异,都会引起安全错误。

      呀发送特定的请求,还必须调用send方法。send方法接收一个参数,即要作为请求主体发送的数据。如果不需要通过请求主体发送数据,必须将参数设置为null,因为这个参数对于有些浏览器来说是必须的。调用send方法后,请求就会被发送到服务器。

      在收到服务端的响应后,响应的数据会自动填充XHR对象的相关属性。详细情况如下:

      responseText:作为响应主体被返回的文本。

      responseXML:如果响应的内容类型是"text/xml或者application/xml",这个属性中将保存着响应数据的XML DOM文档。

      status:响应的HTTP状态。

      statusText:HTTP状态的说明。

      在接收到响应后,第一步操作一般都是验证status属性,以确定响应是否已经成功返回。一般都将200作为成功的标志。这时候,responseText属性的内容已经就绪。此外,状态代码为304表示请求的资源被没有被修改。可以直接使用浏览器中缓存的版本。为确保收到适当的响应。我们应该像下面这样检查这两种状态。例如:

    1 //响应有效
    2 if ((tempxmlhttp.status >= 200 && tempxmlhttp.status < 300) || tempxmlhttp.status == 304) {
    3      callback(tempxmlhttp.responseText, tempxmlhttp.responseXML);
    4 } else {
    5      failback(tempxmlhttp.status, tempxmlhttp.statusText);
    6 }

      在大多数情况下,我们都会使用XHR进行异步访问。这样可以让JavaScript继续执行,而不必为了等待服务端的响应而阻塞代码的执行。我们可以通过XHR的readyState来获取请求/响应过程中的状态。详细的信息如下:

      0---未初始化,尚未调用open方法。

      1---启动,已经调用open方法,尚未调用send方法。

      2---发送,已经调用send方法,但是还没有收到服务端响应。

      3---接收,已经接收到部分响应数据。

      4---完成,已经接收到全部响应数据,可以在客户端使用了。

      只要readyState属性的值由一个值变成另一个值,都会触发readystatechange事件。可以使用这个事件来监测每次状态变化以后的readyState的值。必须在调用open函数之前指定onreadystatechange事件处理程序才能保证跨浏览器兼容性。例子如下:

     1 this.xmlhttprequest.onreadystatechange = function () {
     2         if (tempxmlhttp.readyState == 4) {
     3             //响应有效
     4             if ((tempxmlhttp.status >= 200 && tempxmlhttp.status < 300) || tempxmlhttp.status == 304) {
     5                 callback(tempxmlhttp.responseText, tempxmlhttp.responseXML);
     6             } else {
     7                 failback(tempxmlhttp.status, tempxmlhttp.statusText);
     8             }
     9         }
    10     }
    11     this.xmlhttprequest.open(method, url, true);
    12     this.xmlhttprequest.send(null);

    HTTP头部信息

      每一个Http请求和响应都会带有相应的头部信息。XHR对象也提供相应的方法来操作请求和响应的头部信息。下面我们就来看看XHR在发送请求时。默认携带的Http头部信息。如图:

      使用setRequestHeader方法可以设置请求头的信息,这个方法接收两个参数,头部字段的名称和头部字段的值。必须在调用open方法之后,send方法之前调用setRequestHeader方法

      GET请求

      GET请求是最常用的的请求类型,一般用于向服务器查询某些信息。必要时,可以将查询字符串参数追加到URL尾部,以便将参数发送到服务器。对于XHR而言,对于传入open方法的URL尾部的查询字符串必须经过正确的编码才行。使用GET请求的URL应该是这样:/Home/Index?Id=1&type=book(参数没有编码)。

      我们可以使用一个参数来构造发送给服务端的查询字符串。例如:

     1 /**
     2  * 将JavaScript中的对象解析成查询字符串(key=value&key1=value1的形式)
     3  **/
     4 function appendParameters(data) {
     5     var query = "";
     6     //枚举JS对象的属性
     7     for (var item in data) {
     8         query += (encodeURIComponent(item) + "=" + encodeURIComponent(data[item]));
     9         query += "&";
    10     }
    11     query = query.substr(0, query.length - 1);
    12     return query;
    13 }

      我们可以使用下面的代码来使用XHR来进行GET请求。如下:

    1 url += (url.indexOf("?") == -1) ? "?" : "&";
    2 url += query;
    3 //解决缓存的转换
    4 url += "&t=" + (new Date()).valueOf();
    5 this.xmlhttprequest.open(method, url, true);
    6 this.xmlhttprequest.send(null);

    POST请求

      POST请求是使用频率仅次于GET的请求类型,一般用于向服务器发送应该被保存的数据。POST请求会将数据作为请求的主体进行提交,而GET请求传统上不是这样的。POST请求的主体可以包含非常多的数据,并且格式不限。

      我们可以通过使用XHR来模拟表单的提交行为。需要将Content-Type设置为application/x-www-form-urlencoded也就是表单提交时的内容类型。同时我们需要将数据传递到服务器时,需要使用XHR的send方法来传递数据。使用XHR进行POST调用的例子如下:

    1 //如果是POST方式,需要设置请求头
    2 if (method.toLowerCase() === "post") {
    3         this.xmlhttprequest.open(method, url, true);
    4         this.xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    5         //post传递数据时需要(query是key=value&key1=value1的形式的字符串)
    6         this.xmlhttprequest.send(query);
    7 }

      注意:与GET请求相比,POST请求消耗的资源会更多一些。从性能的角度看,发送相同的数据量,GET请求的数据最多可以达到POST请求的两倍。

    完整的Ajax的例子(已封装)

     1 /**
     2  * 通过XMLHttpRequest来了解Ajax技术的本质.
     3  * 作为约定俗成的准则,JS中构造函数以大写字母开头
     4  **/
     5 function AjaxInstance() {
     6     this.xmlhttprequest = function () {
     7         if (typeof XMLHttpRequest !== "undefined") {
     8             return new XMLHttpRequest();
     9         //适用于IE7之前的版本
    10         } else if (typeof ActiveXObject !== "undefined") {
    11             if (typeof arguments.callee.activeXString !== "string") {
    12                 var versions = ["MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP"];
    13                 for (var i = 0, len = versions.length; i < len; i++) {
    14                     try {
    15                         arguments.callee.activeXString = versions[i];
    16                         return new ActiveXObject(versions[i]);
    17                     } catch (e) { }
    18                 }
    19             }
    20             return new ActiveXObject(arguments.callee.activeXString);
    21         }
    22         else {
    23             alert("您的浏览器版本不支持Ajax技术,请升级新版本浏览器...");
    24         }
    25     }
    26 }
    27 
    28 /**
    29  * 使用XMLHttpRequest对象调用服务端方法
    30  * method:调用ajax的方式:get/post
    31  * url:调用服务端方法的路径(asmx,controller都可).如:Login/CheckUser注意get,post时不要使用?Id=XX&Name=XX等形式.
    32  * data:调用方法时传递的参数.只需要以对象形式{Id:"",Name:""}传递data参数即可,无参传递null
    33  * callback:获取结果的回调函数,会传递结果给回调函数.客户端调用时只需定义具有两个参数的函数即可.如:function callback(responseText,responseXml){}
    34  * failback:出错回调,客户端调用时只需定义具有两个参数的函数即可.如:failback(errorCode,errorMsg),调用该函数时,会将出错Http状态码,出错信息发送给相关参数
    35  **/
    36 AjaxInstance.prototype.call = function (method, url, data, callback, failback) {
    37     //首先判断调用者有无定义相关回调函数
    38     if (!(callback instanceof Function) && !(failback instanceof Function)) {
    39         alert("调用call方法必须指定callback和failback方法");
    40         return;
    41     }
    42     //此处需将this变量赋值给临时变量,若使用this.xmlhttprequest会出现undefined.在function内部使用this指的是window对象.这是JS缺陷
    43     var tempxmlhttp = this.xmlhttprequest;
    44     this.xmlhttprequest.onreadystatechange = function () {
    45         if (tempxmlhttp.readyState == 4) {
    46             //响应有效
    47             if ((tempxmlhttp.status >= 200 && tempxmlhttp.status < 300) || tempxmlhttp.status == 304) {
    48                 callback(tempxmlhttp.responseText, tempxmlhttp.responseXML);
    49             } else {
    50                 failback(tempxmlhttp.status, tempxmlhttp.statusText);
    51             }
    52         }
    53     }
    54 
    55     var query = null;
    56     if (data !== null && (data instanceof Object)) {
    57         query = appendParameters(data);
    58     }
    59     //如果是POST方式,需要设置请求头
    60     if (method.toLowerCase() === "post") {
    61         this.xmlhttprequest.open(method, url, true);
    62         this.xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    63         //post传递数据时需要(query是key=value&key1=value1的形式的字符串)
    64         this.xmlhttprequest.send(query);
    65     }
    66     else {
    67         url += (url.indexOf("?") == -1) ? "?" : "&";
    68         url += query;
    69         //解决缓存的转换
    70         url += "&t=" + (new Date()).valueOf();
    71         this.xmlhttprequest.open(method, url, true);
    72         this.xmlhttprequest.send(null);
    73     }
    74 };
    75 
    76 /**
    77  * 将JavaScript中的对象解析成查询字符串(key=value&key1=value1的形式)
    78  **/
    79 function appendParameters(data) {
    80     var query = "";
    81     //枚举JS对象的属性
    82     for (var item in data) {
    83         query += (encodeURIComponent(item) + "=" + encodeURIComponent(data[item]));
    84         query += "&";
    85     }
    86     query = query.substr(0, query.length - 1);
    87     return query;
    88 }
  • 相关阅读:
    【20210930】连岳摘抄
    【20211002】连岳摘抄
    网站首页head区代码规范(网页设计师必看)
    让你的VMware Workstation随主系统自动启动
    asp中使用图片验证码的方法
    文本筐怎样让它只能输入数字(以及怎么只能输入一个小数点和数字)
    asp通用分页函数
    系统安装秘技:精心打造WinXP万能GHOST(图)
    asp调用存储过程
    在 win2k3 下安装 webeasymail
  • 原文地址:https://www.cnblogs.com/dreamGong/p/4951371.html
Copyright © 2011-2022 走看看