如何在Elm中使用StartApp内的端口

And*_*rle 4 elm

在我的基于StartApp软件包的应用程序中,我有一个端口可以从JS内部进行通信.目前我使用邮箱调用此端口

requestPalette :
  { address : Signal.Address String
  , signal : Signal String
  }
requestPalette = Signal.mailbox ""


requestPaletteFilter : Signal String
requestPaletteFilter =
  Signal.filter (String.isEmpty >> not) "" requestPalette.signal
  |> settledAfter (300 * Time.millisecond)


port request : Signal String
port request = requestPaletteFilter
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

[on "input" targetValue (\str -> Signal.message requestPalette.address str)
Run Code Online (Sandbox Code Playgroud)

我想知道update函数内部是否有一种方法,而不是从视图中发送消息.

Cha*_*ert 5

这适用于elm 0.16(及之前),在elm 0.17订阅已更改为端口

为了从更新中向邮箱发送信号,您需要使用StartApp而不是StartApp.Simple,因为前者允许在update函数中使用效果.

至少,你可能会有这样的Action,它定义了No-Op和发送字符串请求的动作:

type Action
  = NoOp
  | SendRequest String
Run Code Online (Sandbox Code Playgroud)

update现在,您的函数将包含类似于新SendRequest操作的以下情况.由于您正在使用处理效果的StartApp,您必须调用Effects.task,并且您要映射到效果的任务必须是Action类型,这就是我们获得Task.succeed NoOp返回值的原因.

update action model =
  case action of
    NoOp ->
      (model, Effects.none)
    SendRequest str ->
      let
        sendTask =
          Signal.send requestPalette.address str
            `Task.andThen` (\_ -> Task.succeed NoOp)
      in
        (model, sendTask |> Effects.task)
Run Code Online (Sandbox Code Playgroud)

现在,视图中的单击事件处理程序可以返回使用address传递给视图:

  [ on "input" targetValue (Signal.message address << SendRequest) ]
Run Code Online (Sandbox Code Playgroud)

我已经在这个要点中得到了上述实例.您只需要request在javascript中订阅该端口即可查看其中的操作.