上次是最简单的原生JS实现AJAX效果。不过,那简单的步骤不能适应各种不同的浏览器,尤其是万恶的IE,尤其是低版本的IE浏览器。本期就来搞定各个浏览器,以及其他各项参数的设置。

一、服务端代码

服务端代码仍然使用.NET一般处理程序,这次的逻辑略有改动,通过QueryString获取一个key为type的参数,旨在接下来演示AJAX通过GET方式传参。此type属性预设值为“DATE“/”TIME“,如果是”DATE”,服务端就返回当前日期(年月日),否则返回当前时间(时分秒)。 

public class TimeHandler : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        string type = context.Request.QueryString["type"].ToUpper();
        if(type == "DATE")
        {
            context.Response.Write(DateTime.Now.ToLongDateString());
        }
        else
        {
            context.Response.Write(DateTime.Now.ToLongTimeString());
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

二、客户端JS代码

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <script>
        window.onload = function () {
            var btn = document.getElementById("btnTime");
            btn.onclick = function () {
                ////1.声明异步对象
                var xhr = false;                
                //2.根据浏览器类型,创建异步对象 
                if (window.XMLHttpRequest) {
                    xhr = new XMLHttpRequest();
                }
                else {
                    xhr = new ActiveXObject("Microsoft.XMLHTTP");
                }
                //3.从下拉选项框中获取用户选中的选项
                var type = document.getElementById("dType").value;
                //4.拼写url,把get请求传递的参数拼接到url后边
                var url = "timehandler.ashx" + "?type=" + type;
                //5.打开异步对象,并设置参数
                xhr.open("get", url, true);
                //6.设置setRequestHeader,不使用缓存数据
                xhr.setRequestHeader("If-Modified-Since", "0");
                //7.设置回调函数
                xhr.onreadystatechange = function () {
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        var h2 = document.getElementById("time");
                        h2.innerHTML = xhr.responseText;
                    }
                }
                //4.发送异步请求
                xhr.send(null);
            }
        }
    </script>
</head>
<body>
    <select id="dType">
        <option value="DATE">年月日</option>
        <option value="TIME">时分秒</option>
    </select>
    <h2 id="time"></h2>
    <button id="btnTime">点击</button>
</body>
</html>

在客户端,用户通过选择select下拉框中的选项,然后点击btnTime按钮,获取服务器日期或时间。

  与最简化的版本相比,变化点有以下几个

1.异步对象的创建。

   不同的浏览器对于XMLHttpRequest对象的支持不同,这里主要指的是IE,尤其是老版本的IE,它们不支持该对象。IE老版本的浏览器支持的是MS自家的对象ActiveXObject,所以在创建的时候要先做下判断,以兼容老版本IE浏览器。

  其中new ActiveXObject("Microsoft.XMLHTTP")时,传递的参数表示微软的xml语言解析器,用来解释xml语言的。就好像html文本下载到本地,浏览器会检查html的语法,解释html文本然后显示出来一样,不过不仅仅微软有。该也是有变化的,原因是微软在不同版本的浏览器中,对于该参数的解析也不同,所以也有人这么来创建异步对象

var xhr = false;
var msXmlVers = ["MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp", "Microsoft.XMLHttp"];
if (window.XMLHttpRequest) {
    xhr = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
    for (var i = 0; i < msXmlVers.length; i++) {
        xhr = new ActiveXObject(msXmlVers[i]);
        if (xhr) {
            break;
        }
    }
}

其中msXmlVers是个数组,该数组的各个项是不同的msxml解析版本。不过这么写的人貌似不多。

  话又说回来了,现在谁还写原生的Javascript代码来做AJAX?所以这里我们了解就OK了,不求甚解了。

2.GET请求传参

AJAX对于Get请求和Post请求的传参方式是不同的。

  Get请求仍然通过url传参,参数仍然以键值对的形式传递。语法:url?key1=val1&key2=val2&key3=val3.....  ,与普通的get请求传出别无二致。

3.禁用客户端缓存

setRequestHeader是异步对象提供的一个重要的API,它是用来设置请求报文头的。

  这里:xhr.setRequestHeader("If-Modified-Since", "0");是通过设置请求报文头的"If-Modified-Since",来达到禁用客户端缓存数据的目的。   

  至于为什么要禁用客户端缓存数据?

  在http中Last-Modified 与If-Modified-Since 都是用于记录页面最后修改时间的 HTTP 头信息,注意,在这 Last-Modified 是由服务器往客户端发送的 HTTP 头,另一个 If-Modified-Since是由客户端往服务器发送的头,可以看到,再次请求本地存在的 cache 页面时,客户端会通过 If-Modified-Since 头将先前服务器端发过来的 Last-Modified 最后修改时间戳发送回去,这是为了让服务器端进行验证,通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回新的内容,如果是最新的,则 返回 304 告诉客户端其本地 cache 的页面是最新的,于是客户端就可以直接从本地加载页面了,这样在网络上传输的数据就会大大减少,同时也减轻了服务器的负担。而且在一些ajax应用中,要求获取的数据永远是最新的,而不是读取位于缓存中的数据,做这样的设置是非常有必要的。

  那么除了这种方法禁用缓存数据以外,还有一个种方法,就是在请求的url上做手脚。比如:var url = "timehandler.ashx" + "?timestamp=" + new Date().getTime();