原文地址: http:///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 idempotent
method 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, disable
this listener/subscriber // Object "this" points to the
CometD object if (isListener)
this.removeListener(subscriptionHandle); else this.unsubscribe(subscriptionHandle); } 监听器的异常处理程序可以发送消息到服务器。 如果监听器异常处理程序本身抛出一个异常,这个异常记录为“信息”且不破坏CometD实现。 需要注意的是有一个类似的机制扩展存在, 在http:///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()) // Available
since 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频道情况下,可以返回相关细节,例如,验证失败的细节。 |
|
来自: phoneone > 《CometD 2.x》