《JavaScript高级程序设计》读书笔记21.5其他跨域技术

1. 图像Ping

  • 图像 Ping 是与服务器进行简单、单向的跨域通信的一种方式。只能发生”get”请求,不能访问响应文本。

  • 请求的数据是通过查询字符串形式发送的,但浏览器接收不到任何响应的内容,但可以侦听响应什么时候接收到。

    1
    2
    3
    4
    5
    var img = new Image();  
    img.onload = img.onerror = function(){
    alert("Done!");
    };
    img.src = "http://www.example.com/test?name=Nicholas";
  • 图像 Ping最常用于跟踪用户点击页面或动态广告曝光次数。

2. JSONP

  • JSONP 是 JSON with padding(填充式 JSON 或参数式 JSON)的简写,是应用JSON的一种新方法.

  • JSONP 由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的 JSON 数据。

    1
    2
    3
    4
    5
    6
    7
    function handleResponse(response){
    alert("You’ re at IP address " + response.ip + ", which is in " +
    response.city + ", " + response.region_name);
    }
    var script = document.createElement("script");
    script.src = "http://freegeoip.net/json/?callback=handleResponse";
    document.body.insertBefore(script, document.body.firstChild);
  • 两点不足:一是不安全,二是确定JSONP请求是否失败并不容易。

3. Comet

Comet则是一种服务器向页面推送数据的技
术,能够让信息近乎实时地被推送到页面上,非常适合处理体育比赛的分数和股票报价。++
有两种实现 Comet 的方式:长轮询

  • 长轮询
    clipboard.png
    短轮询是服务器立即发送响应,无论数据是否有效。
    clipboard1.png
    长轮询是等待发送响应。
  • HTTP流

什么是http流:浏览器向服务器发送一个请求,而服务器保持连接打开,然后周期性地向浏览器发送数据.
关键:所有服务器端语言都支持打印到输出缓存然后刷新(将输出缓存中的内容一次性全部发送到客户端)的功能。
实现:通过侦听readystatechange事件及检测readyState的值是否为3,IE除外。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function createStreamingClient(url, progress, finished){
var xhr = new XMLHttpRequest(),
received = 0;
xhr.open("get", url, true);
xhr.onreadystatechange = function(){
var result;
if (xhr.readyState == 3){
//只取得最新数据并调整计数器
result = xhr.responseText.substring(received);
received += result.length;
//调用 progress 回调函数
progress(result);
} else if (xhr.readyState == 4){
finished(xhr.responseText);
}
};
xhr.send(null);
return xhr;
}
var client = createStreamingClient("streaming.php", function(data){
alert("Received: " + data);
}, function(data){
alert("Done!");
});

改善:comet容易出错,且浏览器社区认为 Comet 是未来 Web 的一个重要组成部分,为了简化这一技术,又为 Comet 创建了两个新的接口。

4. 服务器发送事件

SSE(Server-SentEvents,服务器发送事件)是围绕只读 Comet交互推出的 API或者模式。
SSE API用于创建到服务器的单向连接,服务器通过这个连接可以发送任意数量的数据。
不支持IE。

4.1 SSE API

要预订新的事件流,首先要创建一个新的 EventSource对象,并传进一个入口点,传入的URL必须同源:

1
var source = new EventSource("myevents.php");

EventSource 的实例有一个readyState属性:

  • 0:表示正连接到服务器
  • 1:表示打开了连接
  • 2:表示关闭了连接

EventSource 的实例有以下三个事件:

  1. open:在建立连接时触发。
  2. message:在从服务器接收到新事件时触发。
  3. error:在无法建立连接时触发。

服务器发回的数据以字符串形式保存在event.data 中。

1
2
3
4
source.onmessage = function(event){ 
var data = event.data;
//处理数据
};

想强制立即断开连接并且不再重新连接,可以调用 close()。

4.2 事件流

  • 服务器事件会通过一个持久的HTTP响应发送,这个响应的MIME类型为text/event-stream。

  • 响应的格式是纯文本,最简单的情况是每个数据项都带有前缀 data:。如下

    1
    2
    3
    4
    5
    6
    data: foo

    data: bar

    data: foo
    data: bar
  • 只有在包含data:的数据行后面有空行时,才会触发 message事件,因此在服务器上生成事件流时不能忘了多添加这一行。

  • 设置ID,可以保证多次连接事件流顺序正确。

5. Web Sockets

Web Sockets的目标是在一个单独的持久连接上提供全双工、双向通信。
使用自定义协议,ws://和wss://
优缺点:

  • 好处是,能够在客户端和服务器之间发送非常少量的数据,而不必担心HTTP那样字节级的开销。适合移动应用。
  • 坏处是,安全隐患。

5.1 Web Sockets API

要创建 Web Socket,先实例一个 WebSocket 对象并传入要连接的 URL,传入绝对URL:

1
var socket = new WebSocket("ws://www.example.com/server.php");

实例化了 WebSocket 对象后,浏览器就会马上尝试创建连接。

表示当前状态的属性:

  1. WebSocket.OPENING (0):正在建立连接。
  2. WebSocket.OPEN (1):已经建立连接。
  3. WebSocket.CLOSING (2):正在关闭连接。
  4. WebSocket.CLOSE (3):已经关闭连接。

5.2 发送和接收数据

  • 发送数据

    • 要向服务器发送数据,使用send()方法
      并传入任意字符串。
    • Web Sockets只能通过连接发送纯文本数据,对于复杂的数据结构,在通过连接发送之前,必须进行序列化成一个JSON字符串
      1
      2
      3
      4
      5
      6
      7
      8
      var socket = new WebSocket("ws://www.example.com/server.php");
      var message = {
      time: new Date(),
      text: "Hello world!",
      clientId: "asdfp8734rew"
      };

      socket.send(JSON.stringify(message));
  • 接收数据
    当服务器向客户端发来消息时,WebSocket 对象就会触发 message 事件。

    1
    2
    3
    4
    5
    socket.onmessage = function(event){ 
    var data = event.data;

    //处理数据
    };

5.3 其他事件

WebSocket 对象还有其他三个事件,在连接生命周期的不同阶段触发。

  1. open:在成功建立连接时触发。
  2. error:在发生错误时触发,连接不能持续。
  3. close:在连接关闭时触发。

6. SSE与Web Sockets

考虑是使用 SSE还是使用 Web Sockets时,可以考虑如下几个因素:

  • 是否有自由度建立和维护 Web Sockets服务器
  • 需不需要双向通信
liborn wechat
欢迎您扫一扫上面的微信二维码,订阅我的公众号!