3

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

我有一个spec由 和 组成renderperformActionrender有权访问该功能dispatch。但是,我需要在渲染元素之前启动 websockets(我可能会将它放入,例如main),但是在消息到达时,我需要理想地dispatch从外部向组件发送一个事件。最好的方法是什么?

4

2 回答 2

5

期望是您将渲染您的组件,获取驱动程序函数的句柄,然后设置您的 websocket 连接并使用驱动程序函数提供更新。

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

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

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

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

于 2016-05-20T16:38:43.830 回答
4

我不确定这是否不是“正确”的方式,但它确实有效。为了访问 websocket 连接,我必须将其放入 State。为了初始化它,我将它放入 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})
于 2016-05-20T18:21:45.197 回答