欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

21.5 其他跨域技术

程序员文章站 2022-07-11 11:40:03
...

一、图像 Ping

根据 img 标签可以从任何网页中加载图像的事实,图像 Ping 创建 Image 实例,在其 src 属性中添加参数,发送到服务器

var img = new Image();
img.onload = img.onerror = function() {
    alert('done');
};
img.src = 'http://www.somewhere.com?name=nicholas';

这种方式有两个缺点:
1.只能发送 GET 请求
2.无法访问服务器的响应文本

二、JSONP

JSONP 是将数据以 JSON 的格式放置在回调函数中响应请求,回调函数的名称一般在请求中指定

function handleResponse(response) { //本地定义回调函数,可以访问响应文本
    alert('name:' + response.name + ',' + 'age:' +response.age);
}
var script = document.createElement('script');
script.src = 'http://www/somewhere.com?callback=handleResponse'; //请求的参数中携带回调函数的名称
document.body.insertBefore(script,document.body.firstChild);

响应的形式

handleResponse({'name':'zz','age':123});

JSONP 可以访问响应文本,支持浏览器与服务器之间双向通信,但是,由于响应中的内容安全性未知,这种方式存在风险;另外,很难确定 JSONP 请求是否失败(script 元素对 onerror 事件的支持度低)

三、Comet

Ajax 用于向服务器请求数据,Comet 用于服务器向页面推送数据,有两种方式:长轮询和流
传统的短轮询指浏览器周期性地向服务器发起请求,服务器接收到请求后立即进行响应
21.5 其他跨域技术
长轮询也是浏览器周期性地向服务器发起请求,但是服务器会在有数据发送时才会进行响应
21.5 其他跨域技术
HTTP 流在页面整个生命周期中只使用一个 HTTP 连接,即浏览器发起请求后,服务器一直保持连接打开,并周期性地向浏览器发送数据

四、服务器发送事件

为了简单的实现 Comet,有了 SSE(Server-Sent Events,服务器发送事件),这是一个用于创建到服务器的单向连接的 API,服务器响应的 MIME 类型必须是 text/event-stream,支持长轮询、短轮询和 HTTP 流,能够在断开连接时自动确定何时重新连接

var source = new EventSource('myevents.php'); //传入的 URL 必须与创建对象的页面同源
source.onmessage = function(event) {
    var data = event.data; //服务器返回的数据以字符串的形式保存在 event.data 中
    //处理数据
};

EventSource 的实例有一个 readyState 属性,0表示正在连接到服务器,1表示打开了连接,2表示关闭了连接
另外,有三个事件

事件 说明
open 在建立连接时触发
message 在从服务器接收到新事件时触发
error 在无法建立连接时触发

若要关闭连接,调用 close 方法

source.close();

服务器响应的数据都带有前缀 data:,且每次 message 事件中的数据最后以空行结束,可以为事件添加关联的 ID,这一行位于data 行前后均可

data:foo
id:1

data:bar

data.foo
data.bar

如上所示,第一次触发 event.data 为 ‘foo’,ID 为1,第三次触发 event.data 为 ‘foo\nbar’
如果意外断开连接,浏览器会向服务器发送一个包含 Last-Event-ID 的特殊 HTTP 头部请求,以便服务器知道下一次该触发哪个事件

五、WebSockets

WebSockets 的目标是在一个单独的持久连接上提供一个全双工、双向通信
其 URL 模式有所不同,未加密的连接不再是 http:// 而是 ws://,同样,加密的连接为 wss://
需要支持 WebSocket 的特殊服务器

var ws = new WebSocket('ws://www.example.com.server.php'); //传入的 URL 必须为绝对路径
ws.send('hello world'); //发送数据
var message = {
    time: new Date(),
    text: 'hello world'
};
ws.send(JSON.stringify(message)); //只能发送纯文本格式的数据,复杂数据需要进行序列化
ws.onmessage = function(event) {
    var data = event.data;
    //处理数据,event.data 属性中的数据也是字符串格式
};
ws.close(); //关闭连接

WebSocket 也有一个表示当前状态的 readyState 属性,但是没有 onreadystatechange 事件

属性值 说明
WebSocket.OPENING(0) 正在建立连接
WebSocket.OPEN(1) 已经建立连接
WebSocket.CLOSING(2) 正在关闭连接
WebSocket.CLOSE(3) 已经关闭连接

WebSocket 对象除 message 外,还有三个其他的事件

事件 说明
open 在成功建立连接时触发
error 在发送错误时触发
close 在连接关闭时触发

WebSocket 对象不支持 DOM2 级事件监听器,故使用 DOM0 级方法添加事件处理程序
上述三个事件中,只有 close 事件的 event 对象有额外的属性

属性 说明
wasClean 连接是否已经明确地关闭
code 服务器返回的数值状态码
reason 字符串,包含服务器发回的消息