Elm - 订阅


在上一章中,我们讨论了视图使用命令与其他组件交互。类似地,组件(例如 WebSocket)可以使用订阅与视图通信。订阅是 Elm 应用程序接收外部输入(如键盘事件、计时器事件和 WebSocket 事件)的一种方式。

下图解释了订阅在 Elm 应用程序中的作用。用户通过消息与 Elm 应用程序交互。给出的应用程序使用 WebSocket,它有两种操作模式 -

  • 通过Command将客户端数据发送到socket服务器
  • 通过订阅随时从套接字服务器接收数据
套接字服务器

句法

定义订阅的语法如下 -

type Sub msg

插图

让我们用一个简单的例子来理解订阅。

在下面给出的示例中,应用程序向服务器发送一条消息。服务器是一个回显服务器,它用相同的消息响应客户端。所有传入的消息稍后都会显示在列表中。我们将使用WebSocket(wss协议)来持续监听来自服务器的消息。WebSocket 将使用命令将用户输入发送到服务器,同时它将使用订阅从服务器接收消息。

应用程序的各个组件如下:

回显服务器

可以使用wss协议访问echo服务器。回显服务器将用户输入发送回应用程序。下面给出了定义回显服务器的代码 -

echoServer : String
echoServer =
"wss://echo.websocket.org"

模型

该模型表示用户输入和来自套接字服务器的传入消息列表。定义模型的代码如下 -

type alias Model =
   { input : String
   , messages : List String
   }

留言

消息类型将包含用于从用户处获取文本输入的输入。当用户单击按钮向 WebSocket 服务器发送消息时,将生成发送消息。当消息从 echo 服务器到达时使用 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 : 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 监听:字符串 -> (字符串 -> 消息) -> 子消息 订阅 websocket 上的任何传入消息。
2 WebSocket.发送 发送:字符串 -> 字符串 -> Cmd 消息 向服务器地址发送 wss 请求。重要的是您也订阅了这个地址并收听。如果没有,将创建 Web 套接字来发送一条消息,然后关闭。

订阅

订阅函数接收模型对象。为了从 WebSocket 服务器接收消息,我们调用WebSocket.listen将消息作为NewMessage传递。当服务器收到新消息时,将调用 update 方法。

subscriptions : Model -> Sub Msg
subscriptions model =
WebSocket.listen echoServer NewMessage

主要的

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

订阅应用程序