在我们平常使用web浏览器访问网站时,大部分都是通过超链接或者是form表单对web服务器发送请求。同时,javascript脚本也可以通过修改window.location变量或者调用表单的submit()方法来让web浏览器发送请求。但这种方式的请求会刷新浏览器的页面。接下来我说的技术就是如何在web浏览器没有加载新页面的情况下发送一个http请求。
Ajax( Asynchronous Javascript and XML)技术,最早出现在2005年2月。这种技术涉及到了js脚本对dom,xml,json等不同文档类型操作,了解http协议状态的情况等等。
XMLHttpRequest对象,在很多书籍中都会有所讲到,实质上相当于浏览器开放了一个HTTP的API接口提供给javascript语言进行操作。所有的操作方法和属性都内置在XMLHttpRequest对象中。如果有一定了解HTTP协议的人,那么对这门技术掌握六七成了。同时请求方式为客户端像服务端主动建立连接,属于客户端推送的方式。那么不多说,我们开始创建一个这样的对象吧。
1.新建XMLHttpRequest对象
var xhr = new XMLHttpRequest(); //创建一个XMLHttpRequest对象。
这种创建方式适合大多数浏览器,如IE7+,FireFox,Chrome,Safari等等。但我们熟知的IE6以前是不支持这种创建方式的,因为以前的IE浏览器是通过加载插件的方式提供这样的接口。接下来的代码就是为了满足现有主流浏览器,创建XMLHttpRequest对象。
function createXHR(){
if( typeof XMLHttpRequest != "undefined"){
return new XMLHttpRequest();
}
if(typeof ActiveXobject == "undefined"){
throw new Error(" not support ");
}
//判断是否为 IE6或IE6以下版本
if(typeof arguments.callee.activeString != "string"){
var versions = ["MSXML2.XMLHttp.6.0",
"MSXML2.XMLHttp3.0","MSXML2.XMLHttp"],
i,len;
for (var i = 0;i<versions.length;i++) {
try{
//尝试使用不同版本的插件新建对象
new ActiveXobject(versions[i]);
//将合适的版本保存至 activeString属性中
//arguments.callee代表的是调用函数,这里指的是createXHR
arguments.callee.activeString=versions[i];
break;
}catch(ex){
// no action
}
};
}
//返回实例对象
return new ActiveXobject(arguments.callee.activeString);
}
这样我们就可以通过以下代码创建具有操作HTTP请求的对象了。
var request = createXHR(); // 函数返回XMLHttpRequest对象
2.建立一个简单的GET请求
在这里,我使用了一个简单的函数,来处理普通的get请求。一般get请求多用于查询操作,因为它自带一定的浏览器缓存,以减少对服务器的压力。
/**
* 发送普通的get请求
* @param {string} url 请求url
* @param {[Object]} data 请求参数
* @param {[Object]} callback 回调函数
*/
function getData(url,data,callback){
var xhr = createXHR(); //新建一个XMLHttpRequest对象
if(arguments.length > 1){
url += "?" + encodeFormData(data);
}
xhr.open("GET",url); //打开一个请求
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && callback){
callback(xhr); //将xhr对象传入回调函数
}
}
xhr.send(null); //请求发送
}
这里出现里一些自定义的函数,以及XMLHttpRequest自带的事件,属性和方法.首先我们说下encodeFormData()函数,这是将对象的属性名和属性值序列化成HTTP协议的请求参数格式 键名1=键值1&键名2=键值2…. 具体的代码如下:
/**
* [encodeFormData 生成合法的请求参数]
* @param {[Object]} data
* @return {[String]}
*/
function encodeFormData(data){
if(!data){ return ""; } // 返回空字符串
var paris=[],name,value;
for(name in data){
if(!data.hasOwnProperty(name)){ continue; } // 跳过继承属性
if(typeof data[name] == "function"){ continue; } //跳过函数类型
name = encodeURIComponent(name.replace('%20','+')); //名称编码
value = encodeURIComponent(data[name].replace('%20','+')); //值编码
paris.push(name+"="+value); //添加到paris数组中
}
return paris.join("&");
}
然后就是xhr.open()方法。这个方法主要有两个必须的部分,请求方式和URL地址。调用这个方法的目的是为了生成请求头部的信息。此时并没有对服务器进行请求操作。这里只是简单的介绍了这个方法。
接下来就是xhr.onreadystatechange 事件。与大多数事件一样,事件名称以on开头。这个事件触发的条件是xhr.readyState的值发生改变。而xhr.readyState总共有5个状态值.
1. UNSET 0 open()尚未调用
2. OPENED 1 open()已调用
3. HEADERS_RECEIVED 2 接收到头信息
4. LOADING 3 接受响应主题
5. DONE 4 响应完成
我们设置了这个触发后执行的函数后,通过判断readyState的值来确定响应是否完成。同时响应携带的信息都会添加到我们新建的xhr实例中去。响应完成后就会执行回调函数。
接下里我们只要使用getData()方法,然后处理获取到服务端的信息。
var url = "http://localhost:8080/home/user/isRegister"; //确保为同服务器的地址,跨域的情况暂时无法处理 主要来验证用户名是否存在
var data ={ username : "liyanlong1993" }; // 字面量对象
getData(url,data,checkRegister); //调用Ajax请求
function checkRegister(res){
//获取响应头部类型
var type = res.getResponseHeader("Content-Type"),
data;
if(type === "application/json"){ //服务器返回的响应头数据格式为json类型
data = JSON.parse(res.responseText);
}else{
alert('请求错误');
console.log('error request');
return ;
}
if(data.result === undefined){
console.log('返回格式不正确');
return ;
}
if(data.result){
console.log('用户已注册');
}else{
console.log('用户尚未注册');
}
}
Ajax请求并非如只可以请求获取XML格式的数据,该例子则是获取JSON格式的数据。实际上得到的是文本数据,服务器端传递过来的响应头部信息为”application/json”。然后通过JSON.parse()方法进行转换。服务端发送的响应的主体如下截图所示:
确实是一个可以转换成JSON数据的文本字符串。
3.小结
整个过程,了解之后其实并不复杂。但Ajax所能做到的并不只是这些,接下来会介绍一些难度有所上升的知识。谢谢大家能看到这里。