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 - 执行后,将生成以下输出: