浅谈JavaScript中的Ajax
引言
作为一名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的更多相关文章
- 浅谈JavaScript中的闭包
浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...
- 浅谈JavaScript中的null和undefined
浅谈JavaScript中的null和undefined null null是JavaScript中的关键字,表示一个特殊值,常用来描述"空值". 对null进行typeof类型运 ...
- 浅谈JavaScript中的正则表达式(适用初学者观看)
浅谈JavaScript中的正则表达式 1.什么是正则表达式(RegExp)? 官方定义: 正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去 ...
- 浅谈jQuery中的Ajax
浅谈jQuery中的Ajax 一.前言 jQuery 对 Ajax 操作进行了封装, 在 jQuery 中最底层的方法时 $.ajax(), 第二层是 load(), $.get() 和 $.post ...
- 浅谈JavaScript中的内存管理
一门语言的内存存储方式是我们学习他必须要了解的,接下来让我浅谈一下自己对他的认识. 首先说,JavaScript中的变量包含两种两种类型: 1)值类型或基本类型:undefined.null.numb ...
- 浅谈JavaScript中的定时器
引言 使用setTimeout()和setInterval()创建的定时器可以实现很多有意思的功能.很多人认为定时器是一个单独的线程(之前我也是),但是JavaScript是运行在单线程环境中的,而定 ...
- 浅谈JavaScript中闭包
引言 闭包可以说是JavaScript中最有特色的一个地方,很好的理解闭包是更深层次的学习JavaScript的基础.这篇文章我们就来简单的谈下JavaScript下的闭包. 闭包是什么? 闭包是什么 ...
- 浅谈JavaScript中的继承
引言 在JavaScript中,实现继承的主要方式是通过原型链技术.这一篇文章我们就通过介绍JavaScript中实现继承的几种方式来慢慢领会JavaScript中继承实现的点点滴滴. 原型链介绍 原 ...
- 浅谈JavaScript中继承的实现
谈到js中的面向对象编程,都有一个共同点,选择原型属性还是构造函数,两者各有利弊,而就片面的从js的对象创建以及继承的实现两个方面来说,官方所推荐的是两个相结合,各尽其责,各取其长,在前面的例子中,我 ...
随机推荐
- Fiddler环境配置教程
原理:安装Fiddler的电脑和将要进行检测的手机(iPhone.Android)加入同一局域网,这样手机上APP的请求就可以被电脑通过Fiddler抓取到. 局域网布置教程: 在将要布置局域网的电脑 ...
- APP图标和启动页
iOS App图标和启动画面尺寸 字数349 阅读22025 评论3 喜欢51 注意:iOS所有图标的圆角效果由系统生成,给到的图标本身不能是圆角的. 1. 桌面图标 (app icon) for i ...
- 用python虚拟串口
在linux下调试串口程序,无奈下面的硬件还没到位,所以,想着自己模拟一个串口用用.试了下下面这段代码: #!/usr/bin/env python #coding=utf-8 import pty ...
- PHP Fatal error: Call to undefined function mb_substr()
Lamp架构 PHP 5.3.29 #查看php是否有mbstring模块 php -m | grep mbstring yum install php-mbstring -y find / -nam ...
- 验证时出错。HRESULT = '8000000A'
往往出现在 做了安装项目后有警告: 解决办法: 这本来是在VS2005下创建的一下项目,后来改用VS2010的开发环境,.NET Framework的版本还是使用2.0, 但每次生成之后都会在解决方案 ...
- 关于 android 开发中 debug不能顺利进行的各种问题的总结
最后一条应该写反了,如果combined hover 取消勾选的话 那么 在写代码时候的悬浮提示就没有了
- Scala Trait
Scala Trait 大多数的时候,Scala中的trait有点类似于Java中的interface.正如同java中的class可以implement多个interface,scala中的cals ...
- HDU 4857 逃生(反向拓扑排序)
传送门 Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前.同时,社 ...
- Linux 命令之 Navicat 连接 Linux 下的Mysql数据库
2016年12月7日18:44:06 -====------------------------ GRANT ALL PRIVILEGES ON *.* TO 'itoffice'@'%' IDEN ...
- java编程思想-java注解
注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据. 一.定义注解 注解的定义看起来很像接口的定义.事实上,与其他任何Java接口一样, ...