《JAVASCRIPT高级程序设计》Ajax与Comet

  Ajax,是Asynchronous JavaScript + XML的简写,这一技术能向服务器请求额外的技术而无需卸载页面,会带给用户更好的体验。Ajax的核心是XMLHttpRequest对象。为了防止XSS(跨站点脚本)、CSRF(跨站点请求伪造)等攻击,Ajax有着同源策略的限制;解决跨域的方式有CORS(跨源资源共享)、图像Ping和JSONP。

  Comet是对Ajax的扩展,让服务器向浏览器推送数据,有长轮询和HTTP流两种方式实现。

  webSocket是一种使用自定义的协议,与服务器进行全双工、双向通信的方式。

一、XMLHttpRequest对象

1、创建

IE7+,firefox,Opera,Chrome和Safari都支持原生的XHR对象,如果要支持IE早期的版本,需要通过MSXML库中的一个ActiveX对象来实现,这个对象又存在三种不同的版本,因此,如果要兼容所有浏览器,创建XHR对象的函数应该这样定义:

    function createXHR(){
        // 先检测原生XMLHttpRequest是否存在
        if(typeof XMLHttpRequest != 'undefined'){
            return new XMLHttpRequest();

        // 检测Active对象是否存在
        }else if(typeof ActiveXObject != 'undefined'){
            if(typeof arguments.callee.activeXString != 'string'){
                // IE中可能有3种不同版本的XML对象
                var versions = ['MSXML2.XMLHttp.6.0','MSXML2.XMLHttp.3.0','MSXML2.XMLHttp'];
            }
            for(var i = 0, len = versions.length;i <len; i++){
                try{
                    new ActiveXObject(versions[i]);
                    arguments.callee.activeXString = versions[i];
                    break;
                }catch(ex){
                    // 什么也不做,跳过
                }
            }
            return new ActiveXObject(arguments.callee.activeXString);
        }else{
            throw new Error('NO XHR object available.');
        }
    }

2、发送请求(get请求为例)

    var xhr = createXHR();
    xhr.open('get', 'example.txt', false); //false表示同步
    xhr.send(null);  //没有数据发送,则写Null

3、接受服务器的响应

在学习如何接受服务器的响应前,先来了解XHR对象与之相关的属性:

《JAVASCRIPT高级程序设计》Ajax与Comet

通过检测readystatechage事件来获取readyState的值,等于4时表示所有数据已经接收完毕,可以进行服务器返回状态的检测了:

    var xhr = createXHR();
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4){
            // 因为有的浏览器会错误的报告204,所以这样书写
            if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304 ){
                alert(xhr.responseText);
            }else{
                alert('Request was unsuccessful: '+xhr.status);
            }
        }
    }
    xhr.open('get','example.txt',true);
    xhr.send(null);

4、设置发送XHR请求时的http头部信息

默认情况下会发送的http头部信息:

  • Accept: 浏览器能够处理的内容类型
  • Accept-Charset:浏览器能够显示的字符集
  • Accept-Encoding: 浏览器能够处理的压缩编码
  • Accept-Language: 浏览器当前设置的语言
  • Connection:浏览器与服务器直接连接的类型
  • Cookie: 当前页面设置的任何cookie
  • Host:发出请求的页面所在的域
  • Referer: 发出请求页面的URI
  • User-Agent:浏览器的用户代理字符串

要发送自定义的请求的头部信息,必须在调用open()和send()之间调用setRequestHeader()方法:

    var xhr = createXHR();
    xhr.open('get','example.txt',true);
    xhr.setRequestHeader('MyHeader', 'MyValue');
    xhr.send(null);

    // 获取相应的头部信息
    var myHeader = xhr.getResponseHeader('MyHeader');
    // 获取所有的头部信息
    var allHeader = xhr.getAllResponseHeaders();

二、XMLHttpRequest2级

XMLHttpRequest 2级进一步发展了XHR,但并非所有的浏览器都完整实现了XMLHttpRequest 2级规范,下面介绍其中新增的部分内容:

1、FormData对象

使用POST方式发送表单时,需要先将表单序列化,并且设置http的Content-Type为applicaition/x-www-form-urlencoded(发送到服务器前,所有内容进行编码的意思);使用FormData对象可以简化操作:

var data = new FormData(document.forms[0]);
xhr.send(data);

2、timeout属性

IE8为XHR添加了一个timeout属性,表示请求在等待响应多少毫秒后终止。

xhr.open('get','test.php',true);
xhr.timeout = 1000;//1秒,仅用于IE8
xhr.ontimeout = function(){
    alert('Request did not return in a second.');
}
xhr.send(null);

3、overrideMimeType()方法

重写MIME类型,例如服务器返回的MIME类型是text/plain,但数据中包含的实际是XML。这个时候,responseXML属性是null。通过调用overrideMimeType()方法,可保证把响应当XML而非纯文本处理。

xhr.open('get','test.php',true);
xhr.overrideMimeType('text/xml');
xhr.send(null);

三、跨资源共享

1、CORS

通过XHR实现Ajax通信的一个主要限制是跨域安全策略,即协议、域名、端口必须完全一致,才能访问。CORS(cross-origin resource sharing,跨域资源共享)是W3C的一个方案,定义了跨域访问时的沟通方式。其基本思想是,使用自定义的HTTP头让浏览器与服务器进行沟通,从而决定请求或响应应该成功还是失败。例如,在服务器端设置:Access-Control-Allow-Origin:* 或者Access-Control-Allow-Origin:指定的IP。

2、图像Ping

原理:利用img标签不存在跨域问题的特性,来与服务器进行简单、单项的跨域通信

缺点:只能发送get请求;无法访问服务器的响应文本

使用场景:跟踪用户点击页面或动态广告的曝光次数

var img = new Image();
img.onload = img.onerror = function(){
    alert('done');
}
img.src = "http://www.baidu.com";

3、JSONP

JSONP是JSON with padding的简写,是通过为动态<script>元素中的src属性指定URL来实现的(与img标签类似)。JSONP由两部分组成:回调函数和数据。例如:callback({'name':'Lillian'});

回调函数中的名字一般是在请求中指定,请求的实际数据是回调函数包裹着的数据。因为JSONP是有效的javascript代码,所以当请求完成后,即JSONP响应加载到页面后,就会立即执行。

优点:支持浏览器和服务器的双向通信

缺点:JSONP从其他域加载代码并执行,其他域的安全性不一定能保证;要确定JSONP请求是否失败,浏览器的事件处理程序支持的并不好。

function handleResponse(response){
    // 请求完成后,代码会立刻执行
}
var script = document.createElement('script');
script.src = 'http://testtest/json?callback=handleResponse';
document.body.insertBefore(script, document.body.firstChild);

三、Comet

Ajax是一种页面向服务器请求数据的技术,Comet是一种服务器向页面推送数据的技术。有两种实现方式:长轮询和流。

短轮询是页面向服务器发起请求后,无论数据是否有效,服务器都立即响应;长轮询是服务器会一直打开,直到有数据可以发送。

HTTP流在整个页面周期内只有一个HTTP连接。它是浏览器向服务器发送一个请求,而服务器保持连接打开,然后周期性的向浏览器发送数据。


四、SSE和WebSocket

SSE是围绕只读Comet交互推出的API或者模式,用于创建到服务器的单向连接,服务器可以通过这个连接发送任意的数据。

WebSocket是在一个单独的持久连接上提供全双工、双向通信。用自定义的ws协议取代了http协议,wss协议取代了https协议。

上一篇:tcp_sync_server and tcp_sync_client


下一篇:ZooKeeper的不同类型的Znodes