
Elm - 訂閱
在上一章中,我們討論了檢視如何使用命令與其他元件互動。類似地,元件(例如 WebSocket)可以使用訂閱與檢視進行通訊。訂閱是 Elm 應用程式接收外部輸入(例如鍵盤事件、計時器事件和 WebSocket 事件)的一種方式。
下圖解釋了訂閱在 Elm 應用程式中的作用。使用者透過訊息與 Elm 應用程式互動。給定的應用程式使用 WebSocket,它有兩種操作模式:
- 透過命令將客戶端資料傳送到套接字伺服器
- 透過訂閱隨時從套接字伺服器接收資料

語法
定義訂閱的語法如下:
type Sub msg
示例
讓我們透過一個簡單的例子來理解訂閱。
在下面的示例中,應用程式向伺服器傳送訊息。伺服器是一個回顯伺服器,它使用相同的訊息回覆客戶端。所有傳入的訊息稍後都會顯示在一個列表中。我們將使用 WebSocket(wss 協議)能夠持續監聽來自伺服器的訊息。WebSocket 將使用命令將使用者輸入傳送到伺服器,同時它將使用訂閱從伺服器接收訊息。
應用程式的各個元件如下:
回顯伺服器
回顯伺服器可以使用 wss 協議訪問。回顯伺服器將使用者輸入傳送回應用程式。定義回顯伺服器的程式碼如下:
echoServer : String echoServer = "wss://echo.websocket.org"
模型
模型表示使用者輸入和來自套接字伺服器的傳入訊息列表。定義模型的程式碼如下:
type alias Model = { input : String , messages : List String }
訊息
訊息型別將包含用於從使用者獲取文字輸入的 Input。當用戶點選按鈕將訊息傳送到 WebSocket 伺服器時,將生成 Send 訊息。當從回顯伺服器收到訊息時,使用 NewMessage。
type Msg = Input String | Send | NewMessage String
檢視
應用程式的檢視包含一個文字框和一個提交按鈕,用於將使用者輸入傳送到伺服器。伺服器的響應使用div標籤顯示在檢視中。
view : Model -> Html Msg view model = div [] [ input [onInput Input, value model.input] [] , button [onClick Send] [text "Send"] , div [] (List.map viewMessage (List.reverse model.messages)) ] viewMessage : String -> Html msg viewMessage msg = div [] [ text msg ]
更新
update 函式接受訊息和模型元件。它根據訊息型別更新模型。
update : Msg -> Model -> (Model, Cmd Msg) update msg {input, messages} = case msg of Input newInput -> (Model newInput messages, Cmd.none) Send -> (Model "" messages, WebSocket.send echoServer input) NewMessage str -> (Model input (str :: messages), Cmd.none)
序號 | 方法 | 簽名 | 描述 |
---|---|---|---|
1 | WebSocket.listen | listen : String -> (String -> msg) -> Sub msg | 訂閱 WebSocket 上的任何傳入訊息。 |
2 | WebSocket.send | send : String -> String -> Cmd msg | 向伺服器地址傳送 wss 請求。重要的是,您也已使用 listen 訂閱了此地址。如果沒有,將建立 WebSocket 來發送一條訊息,然後關閉。 |
訂閱
訂閱函式接收模型物件。為了接收來自 WebSocket 伺服器的訊息,我們呼叫WebSocket.listen,將訊息作為NewMessage傳遞。當從伺服器收到新訊息時,將呼叫 update 方法。
subscriptions : Model -> Sub Msg subscriptions model = WebSocket.listen echoServer NewMessage
main
main 函式是 Elm 應用程式的入口點,如下所示。
main = Html.program { init = init , view = view , update = update , subscriptions = subscriptions }
整合
步驟 1 - 建立一個目錄 SubscriptionApp 並向其中新增一個檔案 SubscriptionDemo.elm。
步驟 2 - 將以下內容新增到 SubscriptionDemo.elm 檔案中:
import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (..) import WebSocket main = Html.program { init = init , view = view , update = update , subscriptions = subscriptions } echoServer : String echoServer = "wss://echo.websocket.org" -- MODEL type alias Model = { input : String , messages : List String } init : (Model, Cmd Msg) init = (Model "" [], Cmd.none) -- UPDATE type Msg = Input String | Send | NewMessage String update : Msg -> Model -> (Model, Cmd Msg) update msg {input, messages} = case msg of Input newInput -> (Model newInput messages, Cmd.none) Send -> (Model "" messages, WebSocket.send echoServer input) NewMessage str -> (Model input (str :: messages), Cmd.none) -- SUBSCRIPTIONS subscriptions : Model -> Sub Msg subscriptions model = WebSocket.listen echoServer NewMessage -- VIEW view : Model -> Html Msg view model = div [] [ input [onInput Input, value model.input] [] , button [onClick Send] [text "Send"] , div [] (List.map viewMessage (List.reverse model.messages)) ] viewMessage : String -> Html msg viewMessage msg = div [] [ text msg ]
步驟 3 - 使用 elm 包管理器安裝 websockets 包。
C:\Users\dell\elm\SubscriptionApp> elm-package install elm-lang/websocket
步驟 4 - 構建並生成 index.html 檔案,如下所示。
C:\Users\dell\elm\SubscriptionApp> elm make .\SubscriptionDemo.elm
步驟 5 - 執行後,將生成以下輸出:
