Purescript thermite и веб-розетки

Я пытаюсь использовать purescript-thermite для создания приложения с использованием веб-сокетов. Идея состоит в том, что приложение подключается к какому-либо серверу с помощью веб-сокетов и обновляет HTML-страницу в реальном времени. Однако я не могу найти способ подключить его к рабочему процессу термитов.

У меня есть spec, состоящий из render и performAction. render имеет доступ к функции dispatch. Однако мне нужно запустить веб-сокеты перед рендерингом элемента (я, вероятно, мог бы поместить его, например, в main), но по прибытии сообщения мне нужно в идеале dispatch событие для компонента извне. Как лучше всего это сделать?


person ondra    schedule 17.05.2016    source источник


Ответы (2)


Ожидается, что вы визуализируете свой компонент, получив дескриптор функции драйвера, затем настроите соединение с веб-сокетом и используете функцию драйвера для предоставления обновлений.

Однако, если вам по какой-то причине необходимо сначала установить соединение с веб-сокетом, вам нужно будет использовать некоторые уловки, возможно, с использованием Ref для удержания функции драйвера после завершения настройки. Таким образом, вам нужно будет вручную проверить, что вы не пытаетесь вызвать функцию драйвера до обновления Ref.

Более продвинутое решение могло бы заключаться в том, чтобы обернуть ваш протокол веб-сокета в форму сопрограммы (см. purescript-coroutines), а также для явного представления любой фазы настройки в типах:

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

Здесь InitialData представляет данные, которые вы получаете во время установки, которые могут быть переданы компоненту, а UpdateMessage представляет ваши инкрементные обновления с сервера, которые будут переданы функции драйвера. Затем вы можете подключить все это к main.

person Phil Freeman    schedule 20.05.2016
comment
Есть ли какой-нибудь пример этой техники? Спасибо! - person Ray Shih; 24.08.2017
comment
Я понял! это тот пример, который дал @ondra - person Ray Shih; 25.08.2017

Я не уверен, что это неправильный способ, но он работает. Чтобы получить доступ к соединению с веб-сокетом, мне пришлось поместить его в состояние. Чтобы инициализировать его, я помещаю его в функцию 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})
person ondra    schedule 20.05.2016