Purescript 铝热剂和 websockets

Purescript thermite and websockets

我正在尝试使用 purescript-thermite 构建一个使用 websockets 的应用程序。这个想法是应用程序使用 websockets 连接到某个服务器并实时更新 HTML 页面。但是,我找不到将其连接到铝热剂工作流程的方法。

我有一个由 renderperformAction 组成的 specrender 可以访问 dispatch 函数。但是,我需要在渲染元素之前启动 websockets(我可能会把它放到 main 中),但是在消息到达时我需要从外部 dispatch 向组件发送一个事件.最好的方法是什么?

期望您呈现您的组件,获取驱动函数的句柄,然后设置您的 websocket 连接并使用驱动函数提供更新。

但是,如果您出于某种原因需要首先设置 websocket 连接,那么您将需要使用一些技巧,可能涉及 Ref 以在设置完成后保持驱动程序功能。这样,您需要手动验证在 Ref 更新之前您没有尝试调用驱动程序函数。

一个更高级的解决方案可能是以协同程序的形式包装您的 websocket 协议(参见 purescript-coroutines),并在类型中显式表示任何设置阶段:

type Connection = 
  Aff MyEffects { initialData :: InitialData
                , updateStream :: Producer (Aff MyEffects) UpdateMessage
                }

此处,InitialData 代表您在设置时收到的数据,可能会传递给组件,UpdateMessage 代表您从服务器增量更新,这将传递给驱动程序功能。然后,您可以将所有这些连接起来 main.

我不确定这是否不是 'right' 方式,但它确实有效。为了访问 websocket 连接,我必须将其放入状态。为了初始化它,我将它放入 componentWillMount 函数中。所以初始化看起来像这样:

type State = {
    conn :: Maybe Connection
}

main :: Eff (...) Unit
main = do
  let rspec = T.createReactSpec spec initialState
  let component = React.createClass $ rspec.spec {componentWillMount=mountInit rspec.dispatcher}

mountInit :: forall props eff.
  (ReactThis props State -> Action ->
      Eff (... | eff) Unit)
  -> ReactThis props State
  -> Eff (... | eff) Unit
mountInit dispatch this = do
  let handlers = {
        connected: log "Service connected"
      , disconnected: log "Disconnected"
      , handle: \msg -> dispatch this (WebsockMsg msg)
    }
  conn <- createConnection "ws://localhost:3000/websock/webclient" handlers
  void $ transformState this (\s -> s{conn= Just conn})