我正在尝试使用purescript-thermite来构建一个使用websockets的应用程序。这个想法是应用程序使用websockets连接到某个服务器并实时更新HTML页面。但是,我找不到如何将其连接到thermite工作流程的方法。
我有一个由spec
和render
组成的performAction
。 render
可以访问dispatch
功能。但是,我需要在渲染元素之前启动websockets(我可能会将其放入main
),但是在消息到达时,我需要理想地dispatch
来自外部的组件事件。最好的方法是什么?
答案 0 :(得分:5)
期望您将渲染组件,获取驱动程序函数的句柄,然后设置websocket连接并使用驱动程序函数来提供更新。
但是,如果由于某种原因需要首先设置websocket连接,那么在设置完成后,您需要使用一些技巧,可能需要Ref
来保存驱动程序功能。这样,您需要手动验证在Ref
更新之前不要尝试调用驱动程序函数。
更高级的解决方案可能是以协程的形式包装您的websocket协议(请参阅purescript-coroutines),并在类型中明确表示任何设置阶段:
type Connection =
Aff MyEffects { initialData :: InitialData
, updateStream :: Producer (Aff MyEffects) UpdateMessage
}
此处,InitialData
表示您在设置时收到的数据,可能会传递给组件,UpdateMessage
表示来自服务器的增量更新,这些更新将传递给驱动程序函数。然后,您可以在main
。
答案 1 :(得分:4)
我不确定它是不是'正确'的方式,但它确实有效。为了访问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})