代码改变世界

AJAX

2011-11-09 00:53  三皮开发时  阅读(312)  评论(0编辑  收藏  举报

曾面试某家公司的时候被问到AJAX

问:AJAX是如何工作的,他的处理方式有什么不同,讲讲你对AJAX分层的概念或者它的MVC处理机制

好吧,当时的确小懵了下

 

最近在看《疯狂AJAX讲义》对AJAX分析的很透彻,现在能明白那个问题的重点了,粗略小记心得

 

AJAX核心:XMLHttpRequest对象

不同浏览器实现这个对象的方式也不同,IE提供ActiveX Object 对象实现,其他浏览器都有各自的实现方式

所以在某种程度上略有不同的,所以在创建XMLHttpRequest对象,需要提供一种能跨浏览器的创建方法,这也是AJAX其中的一个弊端

 

XMLHttpRequest 何用?

它提供了一些属性、方法,正由于这些,才能实现页面异步通信操作

abort()

getAllResponseHeaders()

getResponseHeader("headerLabel")

open("get/post","url",true)

send(null) -空参则请写null,确保跨浏览器

sendRequestHeader("label","value") 发送请求前,配置请求头

 

 

onreadystatechange :readySate状态改变所执行的方法(回调)

readySate:XMLHttpRequest对象的处理状态

responseText:获取服务器的响应文本

responseXML:获取服务器响应的XML文档对象

status:服务器状态

statusText:服务器返回状态及文本信息

 

readySate

0-XMLHttpRequest对象还没有完成初始化

1-XMLHttpRequest对象开始发送请求

2-XMLHttpRequest对象请求发送完成

3-XMLHttpRequest对象读取服务器的响应

4-XMLHttpRequest对象读取服务器响应结束

 

status

404-访问的资源不存在

500-服务器内部错误

403-没有权限访问资源

200-服务器响应正常

400-无法找到请求的资源

...等等

 

《疯狂AJAX讲义》一书中详细的讲述了XMLHttpRequest对象的含义以及用实例说明了各种优缺,现在有很多框架把这些操作都封装了起来

比如 jQuery、prototype 、DWR 等,但是一些纯粹的原理知道的越多越好

 

以下贴一些代码示例,直观

 

first.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title> 发送POST请求 </title>
    <meta name="author" content="Yeeku.H.Lee" />
    <meta name="website" content="http://www.crazyit.org" />
    <meta http-equiv="Content-Type" content="text/html; charset=GBK" />
</head>
<body>
<select name="first" id="first" size="3"
    onchange="change(this.value);">
    <option value="1" selected="selected">中国</option>
    <option value="2">美国</option>
    <option value="3">日本</option>
</select>
<select id="second" size="3"></select>
<script type="text/javascript">
//定义了XMLHttpRequest对象
var xmlrequest;
//完成XMLHttpRequest对象的初始化
function createXMLHttpRequest()
{
    if(window.XMLHttpRequest)
    { 
        //DOM 2浏览器
        xmlrequest = new XMLHttpRequest();
    }
    else if (window.ActiveXObject)
    {
        // IE浏览器
        try
        {
            xmlrequest = new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch (e)
        {
            try
            {
                xmlrequest = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e)
            {
            }
        }
    }
}
//事件处理函数,当下拉列表选择改变时,触发该函数
function change(id)
{
    //初始化XMLHttpRequest对象
    createXMLHttpRequest();
    //确定需要发送的URL
    var uri = "second.jsp";
    //设置以POST方法发送请求,并打开连接
    xmlrequest.open("POST", uri, true); 
    //设置POST请求的请求头
    xmlrequest.setRequestHeader("Content-Type"
        , "application/x-www-form-urlencoded");
    //确定XMLHttpRequest对象的状态改变时的回调函数
    xmlrequest.onreadystatechange = processResponse;
    //发送请求,在发送请求时发送请求参数
    xmlrequest.send("id="+id);
}
//定义处理响应的回调函数
function processResponse()
{
    //响应完成且响应正常
    if (xmlrequest.readyState == 4)
    {
        if (xmlrequest.status == 200)
        {
            //将服务器相应以$符号分隔成字符串数组
            var cityList = xmlrequest.responseText.split("$");
            //获取用于显示菜单的下拉列表
            var displaySelect = document.getElementById("second");
            //将目标下拉列表清空
            displaySelect.innerHTML = null;
            //以字符串数组的每个元素创建option,并将这些选项添加到下拉列表中
            for (var i = 0 ; i < cityList.length ; i++)
            {
                //创建一个<option.../>元素
                var op = document.createElement("option");
                op.innerHTML = cityList[i];
                //将新的选项添加到列表框的最后
                displaySelect.appendChild(op);
            }
        }
        else
        {
            //页面不正常
            window.alert("您所请求的页面有异常。");
        }
    }
}
</script>
</body>
</html>

 

second.jsp

 

<%@ page contentType="text/html; charset=GBK" language="java" %>
<%
//从服务器获取id参数
int id = Integer.parseInt(request.getParameter("id"));
//根据id的值,确定需要返回给客户端的信息,返回客户端的城市信息以$符号隔开
switch(id)
{
    case 1:
%>
上海$广州$北京
<%
    break;
    case 2:
%>
华盛顿$纽约$加洲
<%
    break;
    case 3:
%>
东京$大板$福冈
<%
    break;
}
%>

 

结果是在国家的选择列表中选择某个国家右边的空列表中会自动加载数据显示出对应国家的城市

 

 

一个AJAX公共JS ---作用类似我们的工具类

//使用literal语法定义一个对象:XMLHttp
var XMLHttp = 
{
    //定义第一个属性,该属性用于缓存XMLHttpRequest对象的数组
    XMLHttpRequestPool: [],
    //对象的第一个方法,该方法用于返回一个XMLHttpRequest对象
    getInstance:function()
    {
        // 从XMLHttpRequest对象池中取出一个空闲的XMLHttpRequest
        for (var i = 0; i < this.XMLHttpRequestPool.length; i ++)
        {
            //如果XMLHttpReuqest的readyState为0,或者为4,
            
//都表示当前的XMLHttpRequest对象为闲置的对象
            if (this.XMLHttpRequestPool[i].readyState == 0 || 
                this.XMLHttpRequestPool[i].readyState == 4)
            {
                return this.XMLHttpRequestPool[i];
            }
        }
        //如果没有空闲的,将再次创建一个新的XMLHttpRequest对象
        this.XMLHttpRequestPool[this.XMLHttpRequestPool.length] 
            = this.createXMLHttpRequest();
        //返回刚刚创建的XMLHttpRequest对象
        return this.XMLHttpRequestPool[this.XMLHttpRequestPool.length - 1];
    },
    //创建新的XMLHttpRequest对象
    createXMLHttpRequest:function()
    {
        //对于DOM 2 规范的浏览器
        if (window.XMLHttpRequest)
        {
            var objXMLHttp = new XMLHttpRequest();
        }
        //对于Internet Explorer浏览器
        else
        {
            //将Internet Explorer内置的所有XMLHTTP ActiveX控制设置成数组
            var MSXML = ['MSXML2.XMLHTTP.5.0''MSXML2.XMLHTTP.4.0'
                'MSXML2.XMLHTTP.3.0''MSXML2.XMLHTTP''Microsoft.XMLHTTP'];
            //依次对Internet Explorer内置的XMLHTTP控件初始化,尝试创建XMLHttpRequest对象
            for(var n = 0; n < MSXML.length; n ++)
            {
                try
                {
                    //如果可以正常创建XMLHttpRequest对象,使用break跳出循环
                    var objXMLHttp = new ActiveXObject(MSXML[n]); 
                    break;
                }
                catch(e)
                {
                }
            }
        }
        //Mozilla某些版本没有readyState属性
        if (objXMLHttp.readyState == null)
        {
            //直接设置其readyState为0
            objXMLHttp.readyState = 0;
            //对于哪些没有readyState属性的浏览器,将load动作与下面的函数关联起来
            objXMLHttp.addEventListener("load", function ()
            {
                //当从服务器加载数据完成后,将readyState状态设为4
                objXMLHttp.readyState = 4;
                if (typeof objXMLHttp.onreadystatechange == "function")
                {
                    objXMLHttp.onreadystatechange();
                }
            }, false);
        }
        return objXMLHttp;
    },
    //定义对象的第三个方法: 发送请求(方法[POST,GET], 地址, 数据, 回调函数)
    sendRequest: function (method, url, data, callback)
    {
        var objXMLHttp = this.getInstance();
        with(objXMLHttp)
        {
            try
            {
                //增加一个额外的randnum请求参数,用于防止IE缓存服务器响应
                if (url.indexOf("?") > 0)
                {
                    url += "&randnum=" + Math.random();
                }
                else
                {
                    url += "?randnum=" + Math.random();
                }
                //打开与服务器的连接
                open(method, url, true);
                //对于使用POST请求方式
                if (method == "POST")
                {
                    // 设定请求头
                    setRequestHeader('Content-Type'
                        'application/x-www-form-urlencoded');
                    send(data);
                }
                //对于采用GET请求
                if (method == "GET")
                {
                    send(null);
                }
                //设置状态改变的回调函数
                onreadystatechange = function ()
                {
                    //当服务器的相应完成时,以及获得了正常的服务器响应
                    if (objXMLHttp.readyState == 4 &&
                        (objXMLHttp.status == 200 || 
                            objXMLHttp.status == 304))
                    {
                        //当响应时机成熟时,调用回调函数处理响应
                        callback(objXMLHttp);
                    }
                }
            }
            catch(e)
            {
                alert(e);
            }
        }
    }
};