原文地址: http:///documentation/cometd-javascript/subscription
CometD的JavaScript訂閱 raman在周一,2009年6月29日 - 15:29提交。 JavaScript的CometD API:訂閱和取消訂閱 頻道 Bayeux規(guī)范定義了頻道的概念:它像一個消息的主題,有興趣的人士可以訂閱接收到頻道發(fā)布的信息。 有3種類型的渠道: 元數(shù)據(jù)頻道 服務頻道 正常頻道 一個頻道看起來像一個目錄路徑,如/meta/connect(元數(shù)據(jù)頻道;所有的元數(shù)據(jù)頻道的前綴都是/meta/開始的),或/service/chat(服務頻道;所有服務頻道的前綴都是/service/開始的)或/foo/bar(正常頻道)。 元數(shù)據(jù)頻道 元數(shù)據(jù)頻道由Bayeux協(xié)議本身創(chuàng)建。 訂閱元數(shù)據(jù)頻道這是不可能的:服務器將回復一條錯誤消息。但是,它可能監(jiān)聽元數(shù)據(jù)頻道(見下文訂閱和監(jiān)聽之間的差異)。 發(fā)布消息到元數(shù)據(jù)頻道是沒有意義的:只有Bayeux協(xié)議實現(xiàn)創(chuàng)建和發(fā)送元數(shù)據(jù)頻道的消息。 元數(shù)據(jù)頻道對客戶端監(jiān)聽錯誤消息是非常有用的,像握手錯誤(例如,因為客戶端沒有提供正確的憑據(jù))或網(wǎng)絡錯誤(例如,知道什么時候與服務器的連接斷開了,或它已經(jīng)重新建立了)。 服務頻道 服務頻道在客戶端和服務器以請求/響應的方式進行通信的情況下使用(對應于發(fā)布/訂閱的方式進行通信或正常頻道)。 訂閱服務頻道不會得到錯誤,這相當于對服務器沒有操作:服務器會忽略訂閱請求。 它可以用特定的客戶端(一個發(fā)布消息到服務頻道的客戶端)和服務器之間通信的語義發(fā)布消息到服務頻道。 服務頻道是很有用的實現(xiàn),例如,私人聊天消息:在與userA,userB和userC聊天,userA可以使用服務頻道發(fā)布私人消息給userC(UserB不會知道)。 正常頻道 正常頻道,有一個消息主題的語義,并在發(fā)布/訂閱的通信方式情況下使用。 通常情況下,是可以訂閱正常頻道和發(fā)布消息到正常頻道的,只有在bayeux服務器上使用了安全策略才會禁止。 正常頻道在實現(xiàn)廣播消息給所有訂閱的客戶中是非常有用的,例如,在股票價格變動的情況下。 訂閱者與聽眾 JavaScript的CometD API有2個API來讓頻道訂閱工作: addListener()和removeListener() subscribe()和unsubscribe() addListener()方法: 監(jiān)聽元數(shù)據(jù)頻道的消息必須使用 可用于收聽服務頻道消息(你也可以使用subscribe()) 不應該用來聽正常頻道消息(使用subscribe()代替) 不涉及任何與bayeux服務器的通信,因此可以調(diào)用之前稱為握手的handshake() 是同步的:當它返回時,要保證監(jiān)聽已添加 subscribe()方法: 不得用于收聽元數(shù)據(jù)頻道消息(否則服務器將返回一個錯誤) 可用于收聽服務頻道消息(你也可以使用addListener()) 應該用來監(jiān)聽正常頻道消息 涉及bayeux服務器的通信,因此不能在調(diào)用握手handshake()之前調(diào)用 是異步的:它會立即返回,在bayeux服務器已收到訂閱請求之前 請注意: 調(diào)用subscribe(),當subscribe()返回時,并不意味著您已經(jīng)完成了與服務器的訂閱。 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()。 需要指出的是,你要小心你的應用程序:你一定要取消訂閱,以避免泄漏函數(shù)或不止一次執(zhí)行函數(shù)(因為你可能會錯誤地綁定兩次相同的回調(diào))。 請參閱討論有關使用冪等方法的思想。 在bayeux服務器不可達的情況下,怎么處理subscribe()和unsubscribe()(由于網(wǎng)絡故障,或因為服務器崩潰)? 在subscribe()中。本地監(jiān)聽是第一個加入到該頻道的用戶列表的,然后服務器企圖與它進行通信。如果通信失敗,服務器將不知道,它已經(jīng)將消息發(fā)送到這個客戶端,因此客戶端上的本地監(jiān)聽(雖然目前還是)將永遠不會被調(diào)用。 在unsubscribe(),本地監(jiān)聽是首次從該頻道的用戶列表中刪除的,然后服務器企圖與它通信。如果通信失敗,服務器仍然會發(fā)送消息到客戶端,但不會有本地監(jiān)聽派遣。 偵聽/訂閱的異常處理 如果偵聽或訂閱函數(shù)拋出一個異常(例如,調(diào)用一個未定義的對象,方法等),然后記錄錯誤消息(“調(diào)試”級別)。 然而,有一種方法:定義一個全局監(jiān)聽器的異常處理程序,攔截每次偵聽或訂閱拋出的異常: 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); } 監(jiān)聽器的異常處理程序可以發(fā)送消息到服務器。 如果監(jiān)聽器異常處理程序本身拋出一個異常,這個異常記錄為“信息”且不破壞CometD實現(xiàn)。 需要注意的是有一個類似的機制擴展存在, 在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。 通配符機制也適用于偵聽,因此很這樣可能偵聽所有的元數(shù)據(jù)頻道: cometd.addListener("/meta/*",
function(message) { ... }); 默認情況下,訂閱全局通配符/ * / **返回的結(jié)果是一個錯誤,但這種行為在通過給bayeux服務器指定一個自定義安全政策來改變。 通配符只能被指定在頻道的最后部分,所以這些都是無效的訂閱:/ ** / foo或/ foo /*/bar。 元數(shù)據(jù)頻道列表 這些都是在JavaScript CometD實現(xiàn)的元數(shù)據(jù)頻道: /meta/handshake /meta/connect /meta/disconnect /meta/subscribe /meta/unsubscribe /meta/publish /meta/unsuccessful 當記錄的bayeux消息由JavaScript Cometd實現(xiàn)處理時,每一個元數(shù)據(jù)頻道就會被通知。 有任何失敗都會通知/meta/unsuccessful頻道。 到目前為止,最有趣的是訂閱/meta/connect元數(shù)據(jù)頻道,因為它能返回與bayeux服務器的當前連接狀態(tài)。它可以和/meta/disconnect組合使用。例如,根據(jù)bayeux服務器上的連接狀態(tài),在頁面上顯示一個綠色的“連接”圖標或一個紅色的“斷開”圖標,。 使用/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是使用輪詢服務器。 因此,如果斷開是在一個活動的輪詢期間,這個輪詢將被服務器返回,并觸發(fā)/meta/connect監(jiān)聽器。 執(zhí)行連接邏輯前不進行狀態(tài)的初步檢查驗證。 元數(shù)據(jù)頻道的另一種有趣的用法是在握手時,有一個身份驗證步驟。 在注冊/meta/handshake頻道情況下,可以返回相關細節(jié),例如,驗證失敗的細節(jié)。 |
|
來自: phoneone > 《CometD 2.x》