菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
91
0

跨域(二)

原创
05/13 14:22
阅读数 53028

Comet
Ajax是一种从页面向服务器请求数据的技术,而Comet则是一种服务器向页面推送数据的技术。Comet能够让信息近乎实时地被推送到页面上
有两种实现Comet的方式:长轮询和流

1、轮询

1)短轮询:浏览器定时向服务器发送请求,看有没有更新数据
2)长轮询:页面发送一个到服务器的请求,然后服务器一直保持打开状态,直到有数据可发送。发送完数据之后,浏览器关闭连接,随即又发起一个到服务器的请求

无论是短轮询还是长轮询,浏览器都要在接收数据之前,先发起浏览器向服务器的连接,轮询的优势是所有浏览器都支持,因为使用xhr对象和settimeout()就能实现。
而你要做的是决定什么时候发送请求
2、流
流不同于上述两种轮询,因为它在页面的整个生命周期内只使用一个http连接。具体来说,就是浏览器向服务器发送一个请求,而服务器保持连接打开,
然后周期性地向浏览器发送数据。
通过侦听readystatechange事件及检测readyState的值是否为3,就可以利用xhr对象实现http流

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('localhost/index.php',
    function(data){
        console.log('Received' + data)
    },
    function(data){
        console.log('Done!');
    }
)

这个createStreamingClient()函数接收三个参数:要链接的url、在接收到数据时调用到函数以及关闭这个连接时调用的函数


SSE
SSE(Server-SentEvent,服务器发送事件)。SSE API用于创建到服务器的单向连接,服务器通过这个连接可以发送任意数量的数据。
服务器响应的MIME类型必须是text/event-stream,而且是浏览器中的Javascript API能解析格式输出。SSE支持短轮询、长轮询和HTTP流,
而且能在断开连接时自动确定何时重新连接。
1)SSE API
创建一个新的EventSource对象
eg

var source = new EventSource('myevets.php');

*:传入的URL必须与创建对象的页面同源。EventSource实例有一个readyState属性,值为0表示正连接到服务器,值为1表示打开了连接,值为2表示关闭了连接。
另外,还有以下三个事件

open: 在建立连接时触发。
message: 在从服务器接收到新事件时触发。
error: 在无法建立连接时触发。
source.onmessage = function(event){
var data = event.data;
//处理数据
}

服务器发回的数据以字符串形式保存在event.data中。
默认情况下,EventSource对象会保持与服务器的活动连接。如果连接断开,还会重新连接。这意味着SSE适合长轮询和HTTP流。如果想强制立即断开连接并且不再
重新连接,可以调用close()方法

source.close();

 


Web Sockets
Web Sockets的目标是在一个单独的持久连接上提供全双工、双向通信。标准的http服务器无法实现web sockes。只有支持这种协议的专门服务器才能正常工作。
由于Web Sockets使用了自定义的协议,所以url模式也略有不同。未加密的连接不再是http://,而是ws://;加密的连接也不是https://,而是wss://。SSE
使用自定义协议的好处是,能够在客户端和服务器之间发送非常少量的数据,而不必担心http那样字节级的开销。
1)Web Sockets API

//创建一个Web Sockets实例
var socket = new WebSocket('ws://www.example.com/server.php');

*:必须给WebSocket构造函数传入绝对url。同源策略对Web Sockets不适用,因此可以通过它打开到人和站点到连接。

与xhr类似,WebSocket也有一个表示当前状态到readyState属性。不过,与xhr并不相同。

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

WebSocket没有readystatechange事件;不过,它有其他事件,对应不同到状态。readyState到值永远从0开始。

要关闭Web Socket,可以在任何时候调用close()方法

socket.close();

调用colse()之后,readyState的值立即变为2(正在关闭),而在关闭连接后就会变成3.

2)发送和接收数据

var socket = new WebSocket('ws://www.example.com/server.php');
socket.send('Hello world');

因为Web Sockets只能通过连接发送纯文本数据,对于复杂的数据结构,在通过连接发送之前,必须进行序列化

var message = {
    time: new Date(),
    text: 'Hello world!',
    clientId:'9527'
};
socket.send(JSON.stringify(message));

当服务器向客户端发来消息时,WebSocket对象就会触发message事件。返回数据保存在event.data属性中

socket.onmessage = function(event){
var data = event.data;
    //处理数据
}

3)其他事件

open:在成功建立连接时触发
error:在发生错误时触发。连接不能持续。
close:在连接关闭时触发
var socket = new WebSocket('ws://www.example.com/server.php');
socket.onopen = function(){
    alert('connection established.');
}
socket.onerror = function(){
    alert('connection error.');
}
socket.onclose = function(){
    alert('connection closed.');
}

在这三个事件中,只有close事件的event对象you额外的信息。这个事件的事件对象you是三个额外的属性:

wasClean:是一个布尔值,表示连接是否已经明确地关闭;
code:服务器返回的数值状态码;
reason:一个字符串,包含服务器发回的消息
socket.onclose = function(event){
    console.log('Was clean?' + event.wasClean + ' code=' + event.code + ' reason=' + event.reason);
}

 

使用sse还是web Sockets
1、是否有自由度建立和维护web sockets服务器?
WebSocket协议不同于http,所有现有浏览器不能用于web socket,sse倒是通过常规的http通信,因此现有浏览器都满足需求
2、到底需不需要双向通信
如果只需读取服务器数据,如比赛成绩,那么sse比较容易实现。如果必须双向通信,比如聊天室,那么web sockets显然更好
在不能使用web sockets的情况下,组合xhr和sse也能实现双向通信的

 

发表评论

0/200
91 点赞
0 评论
收藏