引言

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

XMLHttpRequest对象

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

 /**
* 通过XMLHttpRequest来了解Ajax技术的本质.
* 作为约定俗成的准则,JS中构造函数以大写字母开头
**/
function AjaxInstance() {
this.xmlhttprequest = function () {
if (typeof XMLHttpRequest !== "undefined") {
return new XMLHttpRequest();
//适用于IE7之前的版本
} else if (typeof ActiveXObject !== "undefined") {
if (typeof arguments.callee.activeXString !== "string") {
var versions = ["MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP"];
for (var i = 0, len = versions.length; i < len; i++) {
try {
arguments.callee.activeXString = versions[i];
return new ActiveXObject(versions[i]);
} catch (e) { }
}
}
return new ActiveXObject(arguments.callee.activeXString);
}
else {
alert("您的浏览器版本不支持Ajax技术,请升级新版本浏览器...");
}
}
}

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

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

XHR的用法

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

 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表示请求的资源被没有被修改。可以直接使用浏览器中缓存的版本。为确保收到适当的响应。我们应该像下面这样检查这两种状态。例如:

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

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

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

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

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

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

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

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

 this.xmlhttprequest.onreadystatechange = function () {
if (tempxmlhttp.readyState == 4) {
//响应有效
if ((tempxmlhttp.status >= 200 && tempxmlhttp.status < 300) || tempxmlhttp.status == 304) {
callback(tempxmlhttp.responseText, tempxmlhttp.responseXML);
} else {
failback(tempxmlhttp.status, tempxmlhttp.statusText);
}
}
}
this.xmlhttprequest.open(method, url, true);
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(参数没有编码)。

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

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

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

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

POST请求

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

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

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

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

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

 /**
* 通过XMLHttpRequest来了解Ajax技术的本质.
* 作为约定俗成的准则,JS中构造函数以大写字母开头
**/
function AjaxInstance() {
this.xmlhttprequest = function () {
if (typeof XMLHttpRequest !== "undefined") {
return new XMLHttpRequest();
//适用于IE7之前的版本
} else if (typeof ActiveXObject !== "undefined") {
if (typeof arguments.callee.activeXString !== "string") {
var versions = ["MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP"];
for (var i = 0, len = versions.length; i < len; i++) {
try {
arguments.callee.activeXString = versions[i];
return new ActiveXObject(versions[i]);
} catch (e) { }
}
}
return new ActiveXObject(arguments.callee.activeXString);
}
else {
alert("您的浏览器版本不支持Ajax技术,请升级新版本浏览器...");
}
}
} /**
* 使用XMLHttpRequest对象调用服务端方法
* method:调用ajax的方式:get/post
* url:调用服务端方法的路径(asmx,controller都可).如:Login/CheckUser注意get,post时不要使用?Id=XX&Name=XX等形式.
* data:调用方法时传递的参数.只需要以对象形式{Id:"",Name:""}传递data参数即可,无参传递null
* callback:获取结果的回调函数,会传递结果给回调函数.客户端调用时只需定义具有两个参数的函数即可.如:function callback(responseText,responseXml){}
* failback:出错回调,客户端调用时只需定义具有两个参数的函数即可.如:failback(errorCode,errorMsg),调用该函数时,会将出错Http状态码,出错信息发送给相关参数
**/
AjaxInstance.prototype.call = function (method, url, data, callback, failback) {
//首先判断调用者有无定义相关回调函数
if (!(callback instanceof Function) && !(failback instanceof Function)) {
alert("调用call方法必须指定callback和failback方法");
return;
}
//此处需将this变量赋值给临时变量,若使用this.xmlhttprequest会出现undefined.在function内部使用this指的是window对象.这是JS缺陷
var tempxmlhttp = this.xmlhttprequest;
this.xmlhttprequest.onreadystatechange = function () {
if (tempxmlhttp.readyState == 4) {
//响应有效
if ((tempxmlhttp.status >= 200 && tempxmlhttp.status < 300) || tempxmlhttp.status == 304) {
callback(tempxmlhttp.responseText, tempxmlhttp.responseXML);
} else {
failback(tempxmlhttp.status, tempxmlhttp.statusText);
}
}
} var query = null;
if (data !== null && (data instanceof Object)) {
query = appendParameters(data);
}
//如果是POST方式,需要设置请求头
if (method.toLowerCase() === "post") {
this.xmlhttprequest.open(method, url, true);
this.xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//post传递数据时需要(query是key=value&key1=value1的形式的字符串)
this.xmlhttprequest.send(query);
}
else {
url += (url.indexOf("?") == -1) ? "?" : "&";
url += query;
//解决缓存的转换
url += "&t=" + (new Date()).valueOf();
this.xmlhttprequest.open(method, url, true);
this.xmlhttprequest.send(null);
}
}; /**
* 将JavaScript中的对象解析成查询字符串(key=value&key1=value1的形式)
**/
function appendParameters(data) {
var query = "";
//枚举JS对象的属性
for (var item in data) {
query += (encodeURIComponent(item) + "=" + encodeURIComponent(data[item]));
query += "&";
}
query = query.substr(0, query.length - 1);
return query;
}

浅谈JavaScript中的Ajax的更多相关文章

  1. 浅谈JavaScript中的闭包

    浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...

  2. 浅谈JavaScript中的null和undefined

    浅谈JavaScript中的null和undefined null null是JavaScript中的关键字,表示一个特殊值,常用来描述"空值". 对null进行typeof类型运 ...

  3. 浅谈JavaScript中的正则表达式(适用初学者观看)

    浅谈JavaScript中的正则表达式 1.什么是正则表达式(RegExp)? 官方定义: 正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去 ...

  4. 浅谈jQuery中的Ajax

    浅谈jQuery中的Ajax 一.前言 jQuery 对 Ajax 操作进行了封装, 在 jQuery 中最底层的方法时 $.ajax(), 第二层是 load(), $.get() 和 $.post ...

  5. 浅谈JavaScript中的内存管理

    一门语言的内存存储方式是我们学习他必须要了解的,接下来让我浅谈一下自己对他的认识. 首先说,JavaScript中的变量包含两种两种类型: 1)值类型或基本类型:undefined.null.numb ...

  6. 浅谈JavaScript中的定时器

    引言 使用setTimeout()和setInterval()创建的定时器可以实现很多有意思的功能.很多人认为定时器是一个单独的线程(之前我也是),但是JavaScript是运行在单线程环境中的,而定 ...

  7. 浅谈JavaScript中闭包

    引言 闭包可以说是JavaScript中最有特色的一个地方,很好的理解闭包是更深层次的学习JavaScript的基础.这篇文章我们就来简单的谈下JavaScript下的闭包. 闭包是什么? 闭包是什么 ...

  8. 浅谈JavaScript中的继承

    引言 在JavaScript中,实现继承的主要方式是通过原型链技术.这一篇文章我们就通过介绍JavaScript中实现继承的几种方式来慢慢领会JavaScript中继承实现的点点滴滴. 原型链介绍 原 ...

  9. 浅谈JavaScript中继承的实现

    谈到js中的面向对象编程,都有一个共同点,选择原型属性还是构造函数,两者各有利弊,而就片面的从js的对象创建以及继承的实现两个方面来说,官方所推荐的是两个相结合,各尽其责,各取其长,在前面的例子中,我 ...

随机推荐

  1. shell截取字符串的方法

    参考文献: linux中shell截取字符串方法总结 [Linux]如何在Shell脚本中计算字符串长度? 截取字符串的方法一共有八种,主要为以下方法 shell中截取字符串的方法有很多中, ${ex ...

  2. JS 打印功能代码可实现打印预览、打印设置等

      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.or ...

  3. 做哪些优化,才能让 UITabelView 更顺滑?(转)

    原文出处: Alexander Orlov   译文出处:南峰子(@南峰子_老驴) 转载自:ios.jobbole.com/83731/ 我已经在iOS这个最好的移动平台上有几年的开发经验了.在这期间 ...

  4. 简单工厂VS工厂方法

    前言: GOF经典的23种设计模式在IT界现已被广为流传.由于比较长时间没有用了,个人对于不同模式与模式之间的区别也渐渐模糊,故开始重温设计模式的思想.也希望更给对设计模式感兴趣的朋友些许的启发. - ...

  5. 简进祥--iOS开发基础知识

    1:App跳转至系统Settings 跳转在IOS8以上跟以下是有区别的,如果是IOS8以上可以如下设置: NSURL *url = [NSURL URLWithString:UIApplicatio ...

  6. 【BZOJ-1179】Atm Tarjan + SPFA

    1179: [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 2407  Solved: 993[Submit][Status ...

  7. 【BZOJ-3308】九月的咖啡店 最大费用最大流 + 线性筛素数

    3308: 九月的咖啡店 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 159  Solved: 56[Submit][Status][Discuss ...

  8. light oj 1236 分解质因数

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=70017#problem/H 题意:求满足1<=i<=j<=n ...

  9. python图形界面(GUI)设计

    不要问我为什么要用 python 来做这种事,我回到“高兴咋地”也不是不可以,总之好奇有没有好的解决方案.逛了一圈下来,总体上来说,python 图形界面有以下几个可行度比较高的解决方案. 1. py ...

  10. [Android]加密技术

    对称加密无论是加密还是解密都使用同一个key,而非对称加密需要两个key(public key和private key).使用public key对数据进行加密,必须使用private key对数据进 ...