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 - 執行後,將生成以下輸出: