Ajax:开发web应用的新途径

索引

1。AJAX原理

2。AJAX核心——XMLHttpRequest简介


1.AJAX原理

AJAX是Asynchronous JavaScript + XML的简称,它是一系列技术的组合:

经典的网络应用模型是以下面的方式进行工作的:用户在客户端触发一个HTTP请求并返回给服务器。服务器端做了一些处理,比如检索数据,分析数值, 与历史遗留系统(legacy systems)交互然后返回给客户端HTML页面。这是一种较适合网络早期的超文本媒体处理模型,但是使网页适合于超文本的因素并不适用于软件应用。


图一: 网络应用的传统模型(左)与AJAX 模型(右)的对比

这种方式就技术意义而言是一次飞跃,但是就用户体验而言却并没有带来多少提升。当服务器端在做它自己的事的时候,用户在干什么呢?没错,用户在等待。在任务中的每一步,用户都在等待。
显然,当我们设计网络应用的时候,我们不应该让用户傻等。那么如何才能让用户在请求某些服务器资源时不需要等待呢?那就是AJAX。
AJAX通过在用户和服务器之间引入一个Ajax引擎,可以消除Web应用的开始--开始-停止这样的交互过程。
在会话的开始时期,浏览器装载AJAX引擎 ,替代经典模型中“装载一个页面”。这个AJAX引擎是用JavaScript写的并隐藏于框架结构的后面。这个引擎负责翻译用户可见接口并站在用户方与服务器交互。AJAX引擎允许用户以异步的方式进行交互——独立于与服务器的交互。所以用户不再需要盯着沙漏图标或空白windows浏览器以等待服务器来做点什么。

图二: 传统网络应用的异步交互模式(上)与AJAX的异步交互模式(下)的区别
每一个会生成HTTP请求的用户活动通常以JavaScript 的形式调用AJAX引擎。每一个“无需返回服务器端的”用户请求——如简单数据验证,内存中编辑数据以及一些导航——都由AJAX引擎自行处理了。如果引擎需要响应从服务器端返回——如果提交数据用于处理,下载更多的界面数据, 或检索新数据——那么引擎将使用XML来异步这些请求,而无需停止用户与应用的交互。

2.AJAX核心——XMLHttpRequest简介
AJAX描述了Web应用程序的一种架构,其显著特征就是脚本化的HTTP和XMLHttpRequest对象。
在现代浏览器中XMLHttpRequest对象得到很好的支持,并且提供了对HTTP协议的完全访问,包括作出POST和HEAD请求及GET请求的能力。XMLHttpRequest可以同步或异步地返回服务器的请求,并且能以文本或者一个DOM文档的形式返回内容。

使用XMLHttpRequest脚本化HTTP
使用XMLHttpRequest脚本化HTTP有三个步骤:
1.创建一个XMLHttpRequest对象
2.指定HTTP请求并向一个Web服务器提交
3.同步或异步地获取服务器的响应

1).创建一个XMLHttpRequest对象
HTTP._factories = {
    function { return new XMLHttpRequest(); },
    function { return new ActiveXObject("Msxml2.XMLHTTP"); },
    function { return new ActiveXObject("Microsoft.XMLHTTP"); }        
}

HTTP._factory = null

//创建一个XMLHttpRequest对象
HTTP.newRequest = function() {
    if(HTTP._factory != null) {
        return HTTP._factory();
    }
    
    for(var i = 0; i < HTTP._factories.length; i++) {
        try {
            var factory = HTTP._factories[i];
            var request = factory();
            if(request != null) {
                HTTP._factory = factory;
                return request;
            }
        } catch(e) {
            continue;
        }
    }
    
    HTTP._factory = function() {
        throw new Error("XMLHttpRequest not supported");
    }
    HTTP._factory();
}

2).提交一个请求
当创建了一个XMLHttpRequest对象,接着就是向Web服务器提交一个请求。这是一个多步骤的过程。
首先,调用open()方法来提定所请求的URL以及该请求的HTTP方法。
XMLHttpRequest.open(String method, String url[, boolean async[, String username, String password]])
其中HTTP方法method中比较常用的是

a)GET方法:该方法只是下载请求的URL的内容。
b)POST方法:这是大多数HTML表单所使用的方法,它允许指定的变量的值作为请求的一部分。
c)HEADER方法:这个方法要求服务器只是返回和该URL关联的头部。

默认情况下,open()方法设置了一个异步的XMLHttpRequest。将false作为open函数的第3个参数,这是告诉函数同步地而不是异步地获取服务器的响应。通常采用异步响应,但同步响应略为简单。所以首先考虑这种情况。
open()并不实际地向Web服务器发送请求,它只是保存自己的参数。等稍后实际发送请求的时候再使用。在发送请求前必须通过setRequestHeader()来设置所有所需的请求头部。
最后在创建了请求对象之后,调用open()方法并设置头部之后通过send()把请求发送给服务器。

3).同步获取服务器响应
XMLHttpRequest对象不仅保存着所做出的HTTP请求的细节,而且也代表服务器的响应。置open()中async=false,则send()方法是同步的,它会阻塞直到服务器响应为止。一旦它返回,可以使用请求对象的status属性和statusText属性来检查服务器所返回的HTTP状态码和状态码名称。
XMLHttpRequest对象使得服务器的响应通过请求对象的responseText属性成为一个可用的字符串。如果响应是一个XML文档,也可以通过responseXML属性把该文档作为一个DOM Document对象来访问。
XMLHttpRequest对象还提供了对Web服务器所返回的HTTP头部的访问,其中getAllResponseHeaders()将响应的头部作为一个为解析的文本块返回,并且getResponseHeader()返回指定的头部的值。

4).处理一个异步响应
要在异步模式中使用一个XMLHttpRequest,将open()中async置为true,或者省略这个参数。如果这样做,send()方法向服务器发送请求然后立即返回。当服务器响应到达,它通过XMLHttpRequest对象以及之前所说的同步用法相同的属性来使用。那么如何判断服务器响应是否到达呢?通过XMLHttpRequest的onreadystatechange属性来控制。任何时候只要readyState变了,事件句柄函数就被调用。其中readyState是指定一个HTTP请求的状态的整数值。

readyState    含义
0                   open()还没有调用
1                   open()已经调用,但是send()还没有调用
2                   send()已经调用,但服务器还没有响应
3                   正在从服务器接收数据
4                   服务器的响应完成

用于异步请求的一个典型的事件句柄如下所示:
var request = HTTP.newRequest();
request.onreadystatechang = function() {
    if(request.readyState == 4) {
        if(request.status == 200) {
            alert(request.responseText);
        }
    }
}

request.open("GET", url);
request.send(null);
XMLHttpRequestvar request = HTTP.newRequest();
request.onreadystatechange = function() {
    if(request.readyState == 4) {
        if(request.status == 200) {
            alert(request.responseText);
        }
    }
}

request.open("GET", url);
request.send(null);

XMLHttpRequest示例与工具
1)GET工具
//getText()工具
HTTP.getText = function(url, callback) {
    var request = HTTP.newRequest();
    request.onreadystatechange = function() {
        if(request.readyState == 4 && request.status == 200) {
            callback(request.responseText);
        }
    }


    request.open("GET", url);
    request.send(null);
}


//getXML()工具
HTTP.getXML = function(url, callback) {
    var request = HTTP.newRequest();
    request.onreadystatechange = function() {
        if(request.readyState == 4 && request.status == 200) {
            callback(request.responseXML);
        }
    }


    request.open("GET", url);
    request.send(null);
}
2)只获取头部
//getHeaders()工具
HTTP.getXML = function(url, callback, errorHandler) {
    var request = HTTP.newRequest();
    request.onreadystatechange = function() {
        if(request.readyState == 4) {
            if(request.status == 200) {
                callback(HTTP.parseHeaders(request));
            } else {
                if(errorHandler)
                    errorHandler(request.status, request.statusText);
                else
                    callback(null);
            }
        }
    }


    request.open("HEADER", url);
    request.send(null);
}


HTTP.parseHeaders = function(request) {
    var headerText = request.getAllResponseHeaders();
    var headers = {};
    var ls = /^\s*/;
    var rs = /\s*$/;
    
    var lines = headerText.split("\n");
    for(var i = 0; i < lines.length; i++) {
        var line = lines[i];
        if(line.length == 0) continue;
        var pos = line.indexof(":");
        var name = line.substring(0, pos).replace(ls, "").replace(ts, "");
        var value = line.substring(pos+1).replace(ls, "").replace(ts, "");
        headers[name] = value;
    }
    
    return headers;
}
3)POST工具
//post工具
HTTP.post = function(url, values, callback, errorHandler) {
    var request = HTTP.newRequest();
    request.onreadystatechange = function() {
        if(request.readyState == 4) {
            if(request.status == 200) {
                callback(HTTP._getResponse(request));
            } else {
                if(errorHandler)
                    errorHandler(request.status, request.statusText);
                else
                    callback(null);
            }
        }
    }


    request.open("POST", url);
    request.setRequestHeader("Cotent-Type", "application/x-www-form-urlencoded");
    request.send(HTTP.encodeFormData(values));
}


HTTP.encodeFormData = function(data) {
    var pairs = [];
    var regexp = /%20/g; //匹配编码的空格
    
    for(var name in data) {
        var value = data[name].toString();
        var pair = encodeURIComponent(name).replace(regexp, "+") + "=" + encodeURIComponent(value).replace(regexp, "+");
    }
    
    return pairs.join("&");
}


HTTP._getResponse = function(request) {
    switch(request.getResponseHeader("Content-Type")) {
        case "text/xml":
            return request.responseXML;
        
        case "text/json":
        case "text/javascript":
        case "application/javascript":
        case "application/x-javascript":
            return eval(request.responseText);
            
        default:
            return request.responseText;
    }
}

扩展阅读:
《JavaScript权威指南(第5版)》第20章


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值