Rail6 Action Cable 概述
在本指南中,我們將學習Action Cable的工作方式以及如何使用WebSocket將實時通訊功能整合到我們的Rails應用程式中。
我們將在本指南中學習:
- 什麼是 Action Cable 以及前後端整合的概念
- 如何設定 Action Cable
- 如何設定 channels
- 執行以及部署 Action Cable 應用
1 什麼是Action Cable?
Action Cable將WebSockets與Rails應用程式無縫整合 。它允許我們使用Ruby編寫程式碼,使用Rails風格,同時也保證具有高效能和可伸縮性。Action Cable提供了全棧支援,包括客戶端JavaScript框架和伺服器端Ruby框架。我們也能通過Action Cable 訪問用Active Record或選擇ORM編寫的完整模型。
2 術語
Action Cable 使用 WebSockets 代替 HTTP 請求, 與此同時也就引入了一些與 http 不同的概念:
2.1 Connections:連線
Connections 使客戶端和和伺服器形成了關聯. 一個簡單的 Action Cable 服務可以處理多個連線例項. 一個WebSocket連線代表一個連線例項。如果一個使用者使用多個瀏覽器選項卡或裝置,則他們可能會向我們的應用程式開啟多個WebSocket。
2.2 Consumers:消費者
一個使用了 WebSocket 連線的客戶端就是一個 消費者consumer. 在 Action Cable 中,消費者被客戶端的 JavaScript框架建立.
2.3 Channels:通道
每個消費者可以依次訂閱多個通道channel。每個通道都封裝一個邏輯工作單元,這類似於控制器在常規MVC的框架中所做的工作。例如,我們可能有一個ChatChannel
和一個AppearancesChannel
,消費者可以訂閱這兩個渠道中的一個或兩個。但是消費者至少要訂閱一個頻道。
2.4 Subscribers:租戶
當消費者訂閱頻道時,他們就充當了租戶。訂戶與頻道之間的連線被稱為稱為'訂閱'。消費者可以多次訂閱頻道。例如,消費者可以同時訂閱多個聊天室。(請記住,一個真實的使用者可能成為多個消費者,每開啟一個選項卡或者裝置,都會建立一個連線)。
2.5 Pub/Sub:釋出/訂閱
釋出/訂閱(Pub / Sub)或釋出-訂閱(Publish-Subscribe)是指一種訊息佇列範例,通過該佇列,資訊傳送者(釋出者)將資料傳送到抽象類的接收者(訂閱者),而無需指定單個接收者。Action Cable使用這種方法在伺服器和許多客戶端之間進行通訊。
2.6 Broadcastings:廣播
廣播是釋出/訂閱連結,其中廣播者傳送的任何內容都直接傳送到訂閱了當前頻道的訂戶。每個通道可以容納零個或多個廣播。
3 服務端元件
3.1 連線
對於伺服器接受的每個WebSocket連線,都將例項化一個連線物件。該物件成為所有由此物件建立的訂閱者的父物件。連線本身不處理認證和授權之外的任何特定應用程式邏輯。WebSocket連線的客戶端稱為連線的消費者。使用者開啟的每一個瀏覽器選項卡,桌面軟體或裝置都會建立一個消費者-連線對。
連線是ApplicationCable::Connection
的例項,它是 ActionCable::Connection::Base
類的擴充套件。在ApplicationCable::Connection
中,我們可以授權傳入連線,如果可以識別使用者,則可以繼續建立連線。
3.1.1 連線設定
# app/channels/application_cable/connection.rb
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
end
private
def find_verified_user
if verified_user = User.find_by(id: cookies.encrypted[:user_id])
verified_user
else
reject_unauthorized_connection
end
end
end
end
在此identified_by
指定一個連線識別符號,該識別符號可用於以後查詢特定的連線。請注意,任何標記為識別符號的內容都會自動在連線之外建立的任何通道例項上以相同的名稱建立一個 Delegate。
此示例基於以下事實:我們已經在應用程式中的其他位置處理了使用者的身份驗證,並且已經使用使用者ID設定了加密的cookie。
然後,當嘗試建立新的連線時,該cookie會自動傳送到該連線例項,我們可以使用它來設定current_user
。通過標識同一位當前使用者的連線,我們還可以確保以後可以檢索給定使用者的所有開啟的連線(如果刪除或未授權使用者,則有可能斷開所有連線)。
如果我們使用了 session 進行身份驗證,並且我們使用cookie儲存該會話的 session資訊,我們的session cookie名稱是_session
,並且使用者ID名稱是user_id
,那麼我們就可以使用以下方法獲取使用者資訊:
verified_user = User.find_by(id: cookies.encrypted['_session']['user_id'])
3.1.2 異常處理
預設情況下,沒有被處理的異常都會被框架自動捕獲並記錄到日誌中。如果我們想自己全域性處理這些異常,可以使用 rescue from
語法,就像下面這樣:
# app/channels/application_cable/connection.rb
module ApplicationCable
class Connection < ActionCable::Connection::Base
# 使用 report_error 處理 標準異常
rescue_from StandardError, with: :report_error
private
# 自定義處理異常的方法
def report_error(e)
SomeExternalBugtrackingService.notify(e)
end
end
end
3.2 Channels:通道
每個通道都封裝一個邏輯工作單元,這類似於控制器在常規MVC的框架中所做的工作。預設情況下,Rials會建立一個繼承自ActionCable::Channel::Base
類的ApplicationCable::Channel
類作為父類,來封裝通道之間資料共享的邏輯。
3.2.1 父通道設定
# app/channels/application_cable/channel.rb
module ApplicationCable
# 父類
class Channel < ActionCable::Channel::Base
end
end
然後我們就可建立自己的通道類了,例如下面兩個類:ChatChannel
和 AppearanceChannel
# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
end
# app/channels/appearance_channel.rb
class AppearanceChannel < ApplicationCable::Channel
end
然後消費者就可以訂閱這兩個通道或者其中一個了。
3.2.2 訂閱
消費者可以作為“訂閱者”來訂閱通道。然後根據通道使用者傳送的識別符號將生產的訊息傳送到訂閱者。
# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
# Called when the consumer has successfully
# become a subscriber to this channel.
def subscribed
end
end
3.2.3 異常處理
與ApplicationCable::Connection
一樣,我們也可以使用rescue_from
在特定渠道上來處理引發的異常:
# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
rescue_from 'MyError', with: :deliver_error_message
private
def deliver_error_message(e)
broadcast_to(...)
end
end
相關文章
- how BabyFile app transfer files with Windows PC though data cableAPPWindows
- Cable--新虛擬網路架構介紹架構
- Cable:360實現的新虛擬網路架構架構
- patch_id,version, action ,status,action_time,description
- Action With AxiosiOS
- 13.there is no action mapped for namespace and action name associated with contAPPnamespace
- struts2的異常There is no Action mapped for namespace / and action nameAPPnamespace
- Github Action釋出Github
- SSH框架之Action框架
- LeetCode in actionLeetCode
- 自定義 Action Bar
- Node.js in ActionNode.js
- QTP的Action模板QT
- Servlet action is not availableServletAI
- Redux概念之三: Action(動作)與Action Creator(動作建立器)Redux
- jsp include directive, jsp:include action, jsp:plugin action compareJSPlugin
- 使用Virtual Audio Cable軟體實現電腦混音支援電腦錄音
- [vuex] unknown action typeVue
- 課時四:Action操作
- Github Action Workflow 實踐Github
- Spark開發-Action操作Spark
- Android Intent Action 大全AndroidIntent
- v$action_session_historySession
- Action呼叫字首詳解
- jQuery IN ACTION 小筆記jQuery筆記
- Yii2 Action用法
- 概述
- SpringMVC 執行一個action之後跳轉到下一個actionSpringMVC
- 安利 GitHub action - 挺香的Github
- akka-typed(4) - EventSourcedBehavior in action
- 真香!GitHub Action一鍵部署Github
- Github Action 快速上手指南Github
- Ext JS in Action, Second EditionJS
- Action中找不以getDataSource方法
- 老外對MongoDB in Action評述MongoDB
- 求教,求教:程式走不到Action
- vuex核心概念---action、getter、moduleVue
- Django DRF @action 裝飾器Django