| Copyright | (C) 2016-2026 David M. Johnson |
|---|---|
| License | BSD3-style (see the file LICENSE) |
| Maintainer | David M. Johnson <code@dmj.io> |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | None |
| Language | Haskell2010 |
Miso.PubSub
Contents
Description
Overview
Miso.PubSub provides a lightweight publish/subscribe channel for
passing messages between independent Component trees that
do not share a parent-child relationship.
A Topic is an untyped broadcast channel. Any component can
publish a message to it; every component that has called subscribe
on that topic will receive the message as an action.
Quick start
import Miso import Miso.PubSub -- 1. Create a shared topic (typically at the top level or in a shared module) chatTopic :: IOTopicchatTopic =topic-- 2. Subscribe in a component's subs list myChatSub ::Topic->SubAction myChatSub t =subscribet GotMessage -- 3. Publish from any component's update function update :: Action ->Effectp props Model Action update (SendMessage msg) =io_(publishchatTopic msg) update (GotMessage msg) = do ...
API
topic— create a new broadcast channelsubscribe— register a component subscription that receives published valuesunsubscribe— deregister a subscriptionpublish— broadcast a value to all current subscribers
See also
- Miso.Binding — lens-based parent↔child model synchronisation
- Miso.Effect —
Sub,withSink - Miso.Runtime — where
Topic,subscribe,publishare defined
Synopsis
Pub/Sub
A Topic represents a place to send and receive messages. Topic is used to facilitate
communication between Component. Component can subscribe to or publish to any Topic,
within the same Component or across Component.
This requires creating a custom ToJSON / FromJSON. Any other Component
can publish or subscribe to this Topic message. It is a way to provide
loosely-coupled communication between Components.
See publish, subscribe, unsubscribe for more details.
When distributing Component for third-party use, it is recommended to export
the Topic, where message is the JSON protocol.
Since: 1.9.0.0
topic :: MisoString -> Topic a Source #
Smart constructor for creating a Topic message to write to
data Message
= Increment
| Decrement
deriving (Show, Eq, Generic, ToJSON, FromJSON)
arithmetic :: Topic Message
arithmetic = topic "arithmetic"
data Action
= Notification (Result Message)
| Subscribe
| Unsubscribe
update_ :: Action -> Effect parent props Int Action
update_ = case
Unsubscribe ->
unsubscribe arithmetic
Subscribe ->
subscribe arithmetic Notification
Notification (Success Increment) ->
update_ AddOne
Notification (Success Decrement) ->
update_ SubtractOne
Notification (Error msg) ->
io_ $ consoleError ("Decode failure: " <> ms msg)
Since: 1.9.0.0
subscribe :: FromJSON message => Topic message -> (message -> action) -> (MisoString -> action) -> Effect parent props model action Source #
Subscribes a Component to a Topic.
Registers a callback in the component that decodes incoming messages
using its own FromJSON instance and dispatches them to the component's
Sink. If the component is already subscribed to the named topic the
previous callback is replaced.
Because each subscriber uses its own FromJSON, components can use
different Haskell types for the same topic as long as the underlying
JSON is compatible, enabling loose coupling between Component.
data Message = Increment | Decrement
deriving (Show, Eq, Generic, ToJSON, FromJSON)
arithmetic :: Topic Message
arithmetic = topic "arithmetic"
data Action
= Notify Message
| NotifyError MisoString
| Subscribe
| Unsubscribe
| AddOne
| SubtractOne
update_ :: Action -> Effect parent props Int Action
update_ = \case
Subscribe ->
subscribe arithmetic Notify NotifyError
Unsubscribe ->
unsubscribe arithmetic
Notify Increment -> update_ AddOne
Notify Decrement -> update_ SubtractOne
NotifyError msg ->
io_ $ consoleError ("Decode failure: " <> msg)
AddOne -> _count += 1
SubtractOne -> _count -= 1
Since: 1.9.0.0
unsubscribe :: Topic message -> Effect parent props model action Source #
publish :: ToJSON message => Topic message -> message -> IO () Source #
Publish to a t'Topic message'
t'Topic message' are generated dynamically if they do not exist. When using publish
all subscribers are immediately notified of a new message. A message is distributed as a Value
The underlying ToJSON instance is used to construct this Value.
We recommend documenting a public API for the JSON protocol message when distributing a Component
downstream to end users for consumption (be it inside a single cabal project or across multiple
cabal projects).
arithmetic :: Topic Message
arithmetic = topic "arithmetic"
server :: Component parent props () Action
server = component () update_ $ () ->
div_
[]
[ "Server component"
, button_ [ onClick AddOne ] [ "+" ]
, button_ [ onClick SubtractOne ] [ "-" ]
, component_ (client_ "client 1")
, component_ (client_ "client 2")
] where
update_ :: Action -> Effect parent props () Action
update_ = case
AddOne ->
publish arithmetic Increment
SubtractOne ->
publish arithemtic Decrement
Since: 1.9.0.0