Elm - 訂閱



在上一章中,我們討論了檢視如何使用命令與其他元件互動。類似地,元件(例如 WebSocket)可以使用訂閱與檢視進行通訊。訂閱是 Elm 應用程式接收外部輸入(例如鍵盤事件、計時器事件和 WebSocket 事件)的一種方式。

下圖解釋了訂閱在 Elm 應用程式中的作用。使用者透過訊息與 Elm 應用程式互動。給定的應用程式使用 WebSocket,它有兩種操作模式:

  • 透過命令將客戶端資料傳送到套接字伺服器
  • 透過訂閱隨時從套接字伺服器接收資料
socket server

語法

定義訂閱的語法如下:

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

SubscriptionApp
廣告