對於嚴重依賴即時客戶端-伺服器通訊的應用程式(例如,點對點聊天和社交網路應用程式)而言,傳送和監聽 socket 事件可能很快變得難以負荷。Sails 透過引入resourceful PubSub(發布/訂閱)的概念,幫助消除與 socket 事件相關的一些複雜性。您應用程式中的每個模型都自動配備了 resourceful PubSub 方法,這些方法為廣播通知和將 socket 訂閱到關於個別資料庫記錄的通知,提供了傳統的、以資料為中心的介面。
如果您的應用程式目前正在使用 blueprint API,那麼您已經在使用 resourceful PubSub 方法了!它們嵌入在 Sails 捆綁的預設 blueprint 行動中,並且在這些行動執行時自動調用,導致在獲取資料時訂閱請求 socket,並在資料變更時將訊息廣播到已訂閱的 socket。(Socket 可以透過調用 .subscribe()
或由於先前對 find
或 findOne
blueprints 的 socket 請求而訂閱。)
即使在編寫自訂程式碼時,您也可以手動調用本節中描述的方法,以取代直接使用 sails.sockets.*
方法。將 resourceful PubSub 方法視為一種標準化應用程式中 socket 通訊介面的方式——這些介面元素可能是房間名稱、作為 socket 訊息傳輸的資料的 schema,或 socket 事件的名稱。這些方法專門為一個或多個使用者介面正在監聽 socket 事件以保持與後端同步的情境而設計。如果這不符合您的使用案例,或者如果您在決定時遇到困難,請別擔心;只需直接調用 sails.sockets.broadcast()
、sails.sockets.join()
或 sails.sockets.leave()
即可。使用任一種方法,甚至在同一個應用程式中同時使用兩種方法,都是完全可以接受的。
Sails 公開了三種不同的 resourceful PubSub (RPS) 方法:.publish()
、.subscribe()
和 .unsubscribe()
。
為了更深入地理解 resourceful PubSub 方法,您可能會發現先熟悉底層的 sails.sockets.*
方法很有用。這是因為每個 RPS 方法或多或少只是對較簡單的 sails.sockets.*
方法之一的上下文包裝器
.publish()
就像sails.sockets.broadcast()
.subscribe()
就像sails.sockets.join()
.unsubscribe()
就像sails.sockets.leave()
這些方法與 sails.sockets.*
中的對應方法之間的最大區別在於,RPS 方法公開了更高等級的介面。例如,RPS 方法在幕後為您選擇房間名稱,並且它們會根據您模型的 identity 推斷出傳統的事件名稱。
雖然您可以自由使用任何 JavaScript 函式庫來監聽客戶端上的 socket 事件,但 Sails 提供了自己的 socket 客戶端,名為 sails.io.js
,作為從任何支援 Socket.IO 的網頁瀏覽器或 Node.js 程序與 Sails 伺服器通訊的便捷方式。使用 Sails socket 客戶端可以輕鬆監聽 resourceful PubSub 事件,就像
io.socket.on('<model identity>', function (msg) {
});
模型 identity 通常是模型名稱的小寫版本,除非它已在模型檔案中手動配置。
假設您的應用程式中有一個名為 User
的模型,其中包含單個“name”屬性。首先,我們將為“user”事件新增一個監聽器
io.socket.on('user', function(msg){
console.log(msg);
})
只要這些 socket 通知的事件名稱為“user”,這就會將我們的客戶端 socket 收到的任何通知記錄到控制台中。但是,在我們將此客戶端 socket 訂閱到一個或多個現有的 User
記錄(在我們的伺服器端程式碼中)之前,我們實際上不會收到這些訊息。
如果您的應用程式啟用了 blueprint API,那麼將客戶端 socket 訂閱到 User
記錄就非常容易了。除了獲取資料外,如果透過 socket 請求存取 “Find” blueprint 行動,則它會自動調用 User.subscribe()
(一個 resourceful PubSub 方法)。
例如,假設您編寫了一些客戶端程式碼,該程式碼向 https://127.0.0.1:1337/user
發送 socket GET
請求
io.socket.get('/user', function(resData) {
console.log(resData);
});
當它執行時,它將命中“Find” blueprint 行動,該行動從 Sails 伺服器返回目前的使用者列表。如果我們發送了正常的 HTTP 請求(例如 jQuery.get('/user')
),那麼這就是將會發生的全部。但是,由於我們發送了socket 請求,伺服器也將我們的客戶端 socket 訂閱到關於返回的使用者記錄的未來通知(調用 .publish()
)。
有關使用
sails.io.js
客戶端發送虛擬請求的更多資訊,請參閱io.socket.get()
。
與 .subscribe()
不同,RPS .publish()
方法可以從任何地方執行——作為 socket 請求結果觸發的控制器行動、AJAX 請求,甚至來自命令列的 cURL 請求。或者,可以從自訂 helper 或命令列腳本中調用 .publish()
。
繼續上面的範例,如果您要開啟另一個瀏覽器視窗並轉到以下 URL
/user/create?name=joe
您會在原始視窗的控制台中看到如下內容
{
verb: 'created',
id: 1,
data: {
id: 1,
name: 'joe',
createdAt: '2014-08-01T05:50:19.855Z'
updatedAt: '2014-08-01T05:50:19.855Z'
}
}
您在此處看到的是一個字典(又名純 JavaScript 物件),它是由 “Create” blueprint 行動 廣播的。在 blueprint API 的情況下,此資料的格式是標準化的,但在您的應用程式中,您可以使用 .publish()
來廣播您喜歡的任何資料。