从 PureScript Flame 应用程序接收信号

Receiving signals from a PureScript Flame application

我正在尝试更好地理解 PureScript 通道和信号,特别是它们在 UI 库 Flame.

中的使用

我创建了以下示例作为一个小示例:

module Main where

import Prelude
import Effect (Effect)
import Flame (Html, QuerySelector(..))
import Flame.Application.NoEffects as FAN
import Flame.HTML.Attribute as HA
import Flame.HTML.Element as HE

data Message
  = ButtonOne
  | ButtonTwo

type Model
  = { buttonOneCount :: Int
    , buttonTwoCount :: Int
    }

init :: Model
init =
  { buttonOneCount: 0
  , buttonTwoCount: 0
  }

update :: Model -> Message -> Model
update model message = case message of
  ButtonOne -> model { buttonOneCount = model.buttonOneCount + 1 }
  ButtonTwo -> model { buttonTwoCount = model.buttonTwoCount + 1 }

view :: Model -> Html Message
view model =
  HE.main "main"
    [ HE.button [ HA.onClick ButtonOne ] "Button One"
    , HE.p_ ("button one: " <> show model.buttonOneCount)
    , HE.button [ HA.onClick ButtonTwo ] "Button Two"
    , HE.p_ ("button two: " <> show model.buttonTwoCount)
    ]

main :: Effect Unit
main = do
  -- flameChannel :: Channel (Array Message)
  flameChannel <-
    FAN.mount (QuerySelector "main")
      { init, update, view }
  pure unit

我知道任何更改都应在 update 中处理,但作为实验,我想在 main 和 [= 中订阅对 flameChannel 的更改38=] 一些代码基于 Message Flame 通过该通道发送。

刚开始,当用户单击按钮一或按钮二时,可以添加什么来使此输出到 JavaScript 控制台,使用 main 中的 flameChannel

我试过使用 purescript-signal 中的各种函数组合:subscriberunSignalget,但没有成功。我还查看了 GitHub 上使用 purescript-signal 库的各种游戏,但它们似乎只是将 runSignal 放入代码中,一切正常,我不明白为什么(也,这些示例有点复杂,与我想要做的相去甚远)。

好的,让我们看看 - 正如您已经注意到的,您会收到一个 Channel(来自信号),它将通知您有关 Messages

您现在应该可以使用 Signal.Channel.subscribe 将其转换为 Signal

现在 Signal 的工作方式是你应该提供一个 Signal signaling Effects(那些将是 executed/run) 到 runSignal - 所以你必须先把你的 Signal (Array Message) 变成 Signal (Effect Unit)

幸运的是 Signal 是一个 Functor,因此您可以使用 map 或提供的 ~>(翻转 map)来执行此操作。我建议先使用 flattenArray 让您的生活更轻松:

logMessage :: Message -> Effect Unit
logMessage msg =
   case msg of
      ButtonOne -> log "button one"
      ButtonTwo -> log "button two"

并在 main 中:

main = do
  flameChannel <-
    FAN.mount (QuerySelector "main")
      { init, update, view }
  let logSignal = 
    map logMessage $ flip flattenArray ButtonOne $ subscribe flameChannel
  runSignal logSignal

这应该有效


免责声明:我没有尝试编译这个 - 如果您遇到任何问题,请报告,我会处理的