何以笙箫默电影音乐:CometD的JavaScript订阅
来源:百度文库 编辑:偶看新闻 时间:2024/04/28 06:15:18
原文地址:
http://cometd.org/documentation/cometd-javascript/subscription
CometD的JavaScript订阅
raman在周一,2009年6月29日 - 15:29提交。
JavaScript的CometD API:订阅和取消订阅
频道
Bayeux规范定义了频道的概念:它像一个消息的主题,有兴趣的人士可以订阅接收到频道发布的信息。
有3种类型的渠道:
元数据频道
服务频道
正常频道
一个频道看起来像一个目录路径,如/meta/connect(元数据频道;所有的元数据频道的前缀都是/meta/开始的),或/service/chat(服务频道;所有服务频道的前缀都是/service/开始的)或/foo/bar(正常频道)。
元数据频道
元数据频道由Bayeux协议本身创建。
订阅元数据频道这是不可能的:服务器将回复一条错误消息。但是,它可能监听元数据频道(见下文订阅和监听之间的差异)。
发布消息到元数据频道是没有意义的:只有Bayeux协议实现创建和发送元数据频道的消息。
元数据频道对客户端监听错误消息是非常有用的,像握手错误(例如,因为客户端没有提供正确的凭据)或网络错误(例如,知道什么时候与服务器的连接断开了,或它已经重新建立了)。
服务频道
服务频道在客户端和服务器以请求/响应的方式进行通信的情况下使用(对应于发布/订阅的方式进行通信或正常频道)。
订阅服务频道不会得到错误,这相当于对服务器没有操作:服务器会忽略订阅请求。
它可以用特定的客户端(一个发布消息到服务频道的客户端)和服务器之间通信的语义发布消息到服务频道。
服务频道是很有用的实现,例如,私人聊天消息:在与userA,userB和userC聊天,userA可以使用服务频道发布私人消息给userC(UserB不会知道)。
正常频道
正常频道,有一个消息主题的语义,并在发布/订阅的通信方式情况下使用。
通常情况下,是可以订阅正常频道和发布消息到正常频道的,只有在bayeux服务器上使用了安全策略才会禁止。
正常频道在实现广播消息给所有订阅的客户中是非常有用的,例如,在股票价格变动的情况下。
订阅者与听众
JavaScript的CometD API有2个API来让频道订阅工作:
addListener()和removeListener()
subscribe()和unsubscribe()
addListener()方法:
监听元数据频道的消息必须使用
可用于收听服务频道消息(你也可以使用subscribe())
不应该用来听正常频道消息(使用subscribe()代替)
不涉及任何与bayeux服务器的通信,因此可以调用之前称为握手的handshake()
是同步的:当它返回时,要保证监听已添加
subscribe()方法:
不得用于收听元数据频道消息(否则服务器将返回一个错误)
可用于收听服务频道消息(你也可以使用addListener())
应该用来监听正常频道消息
涉及bayeux服务器的通信,因此不能在调用握手handshake()之前调用
是异步的:它会立即返回,在bayeux服务器已收到订阅请求之前
请注意:
调用subscribe(),当subscribe()返回时,并不意味着您已经完成了与服务器的订阅。
addListener()和subscribe()都返回一个订阅对象,必须分别通过removeListener()和unsubscribe()来取消订阅:
/ /一些初始化代码
var subscription1= cometd.addListener('/meta/connect', function() { ... });
var subscription2= cometd.subscribe('/foo/bar/', function() { ... });
/ /一些初始化代码
cometd.unsubscribe(subscription2);
cometd.removeListener(subscription1);
一个常见的模式是利用幂等方法来处理,像这样:
var _subscription;
// The idempotentmethod
function_refresh()
{
_appUnsubscribe();
_appSubscribe();
}
function_appUnsubscribe()
{
if (_subscription)
cometd.unsubscribe(_subscription);
_subscription = null;
}
function_appSubscribe()
{
_subscription =cometd.subscribe('/foo/bar', function() { ... });
}
当然,同样也适用于addListener()/ removeListener()。
需要指出的是,你要小心你的应用程序:你一定要取消订阅,以避免泄漏函数或不止一次执行函数(因为你可能会错误地绑定两次相同的回调)。
请参阅讨论有关使用幂等方法的思想。
在bayeux服务器不可达的情况下,怎么处理subscribe()和unsubscribe()(由于网络故障,或因为服务器崩溃)?
在subscribe()中。本地监听是第一个加入到该频道的用户列表的,然后服务器企图与它进行通信。如果通信失败,服务器将不知道,它已经将消息发送到这个客户端,因此客户端上的本地监听(虽然目前还是)将永远不会被调用。
在unsubscribe(),本地监听是首次从该频道的用户列表中删除的,然后服务器企图与它通信。如果通信失败,服务器仍然会发送消息到客户端,但不会有本地监听派遣。
侦听/订阅的异常处理
如果侦听或订阅函数抛出一个异常(例如,调用一个未定义的对象,方法等),然后记录错误消息(“调试”级别)。
然而,有一种方法:定义一个全局监听器的异常处理程序,拦截每次侦听或订阅抛出的异常:
cometd.onListenerException =function(exception, subscriptionHandle, isListener, message)
{
// Uh-oh, something went wrong, disablethis listener/subscriber
// Object "this" points to theCometD object
if (isListener)
this.removeListener(subscriptionHandle);
else
this.unsubscribe(subscriptionHandle);
}
监听器的异常处理程序可以发送消息到服务器。
如果监听器异常处理程序本身抛出一个异常,这个异常记录为“信息”且不破坏CometD实现。
需要注意的是有一个类似的机制扩展存在,
在http://cometd.org/documentation/cometd/ext可以看到。
通配符订阅
可以一次使用通配符来订阅几个频道,比如:
cometd.subscribe("/chatrooms/*",function(message) { ... });
一个星号的意思是匹配一个单一频道段,所以在上面的例子,它将匹配频道/chatrooms/12 和 /chatrooms/15, 而不是 /chatrooms/12/upload。
为了匹配多个频道细分,使用两个星号:
cometd.subscribe("/events/**",function(message) { ... });
两个星号将匹配/events/stock/FOO 和 /events/forex/EUR, 以及 /events/feed 和 /events/feed/2009/08/03。
通配符机制也适用于侦听,因此很这样可能侦听所有的元数据频道:
cometd.addListener("/meta/*",function(message) { ... });
默认情况下,订阅全局通配符/ * / **返回的结果是一个错误,但这种行为在通过给bayeux服务器指定一个自定义安全政策来改变。
通配符只能被指定在频道的最后部分,所以这些都是无效的订阅:/ ** / foo或/ foo /*/bar。
元数据频道列表
这些都是在JavaScript CometD实现的元数据频道:
/meta/handshake
/meta/connect
/meta/disconnect
/meta/subscribe
/meta/unsubscribe
/meta/publish
/meta/unsuccessful
当记录的bayeux消息由JavaScript Cometd实现处理时,每一个元数据频道就会被通知。
有任何失败都会通知/meta/unsuccessful频道。
到目前为止,最有趣的是订阅/meta/connect元数据频道,因为它能返回与bayeux服务器的当前连接状态。它可以和/meta/disconnect组合使用。例如,根据bayeux服务器上的连接状态,在页面上显示一个绿色的“连接”图标或一个红色的“断开”图标,。
使用/meta/connect ,/meta/disconnect频道,这是一种常见的模式:
var _connected =false;
cometd.addListener('/meta/connect',function(message)
{
// if (cometd.getStatus() == 'disconnecting'|| cometd.getStatus() == 'disconnected')
if (cometd.isDisconnected()) // Availablesince 1.1.2
{
return;
}
var wasConnected = _connected;
_connected = message.successful;
if (!wasConnected && _connected)
{
// Reconnected
}
else if (wasConnected &&!_connected)
{
// Disconnected
}
});
cometd.addListener('/meta/disconnect',function(message)
{
if (message.successful)
{
_connected = false;
}
}
/meta/connect频道的一个小的需要注意的是/meta/connect是使用轮询服务器。
因此,如果断开是在一个活动的轮询期间,这个轮询将被服务器返回,并触发/meta/connect监听器。
执行连接逻辑前不进行状态的初步检查验证。
元数据频道的另一种有趣的用法是在握手时,有一个身份验证步骤。
在注册/meta/handshake频道情况下,可以返回相关细节,例如,验证失败的细节。